Warning: session_start(): open(/var/lib/php/sessions/sess_cn0mqno7vbta79i6tj9a0t3pea, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
// The idea is to leave max as the actual number of cores the system
// has (numberOfCores()), and in case of being fully booked, raise an
// alert (customerMustWaitAlert) which can be handled by a strategy
// object (different reactions are possible).
// If nothing is done in such an event, clients are processed serially
// (no guarantees of order), split up among the available threads.
sclass ThreadPool is AutoCloseable {
int max = numberOfCores();
new Set used;
new Set free;
bool retired;
*() {}
*(int *max) {}
synchronized int total() { ret l(used)+l(free); }
synchronized bool nothingAvailable() { ret empty(free) && total() < max; }
event customerMustWaitAlert;
void fireCustomerMustWaitAlert {
vmBus_send customerMustWaitAlert(this, currentThread());
customerMustWaitAlert();
}
synchronized Thread acquireThread(Runnable action) ctex {
checkNotRetired();
while (nothingAvailable()) {
if (total() < max) {
free.add(newThread());
break;
}
fireCustomerMustWaitAlert();
wait();
checkNotRetired();
}
PooledThread t = first(free);
t.addWork(action); // will move it from free to used
ret t;
}
class PooledThread extends Thread {
*(S name) { super(name); }
AppendableChain q;
synchronized Runnable _grabWork() {
Runnable r = first(q);
q = popFirst(q);
if (r == null)
threadIdling(this);
ret r;
}
run {
while ping (!retired()) {
Runnable r = _grabWork();
if (r != null)
pcall { r.run(); }
else {
synchronized { wait(); }
}
}
}
// append to q (do later)
void addWork(Runnable r) {
if (r == null) ret;
synchronized {
if (isEmpty(q))
markUsed(this);
q = chainPlus(q, r);
notify();
}
}
}
PooledThread newThread() {
PooledThread t = new("Thread Pool Inhabitant " + n2(total()+1));
t.start();
ret t;
}
synchronized void threadIdling(PooledThread t) {
used.remove(t);
free.add(t);
notifyAll();
}
synchronized void markUsed(PooledThread t) {
free.remove(t);
used.add(t);
}
synchronized toString {
ret retired()
? "Retired ThreadPool"
: "ThreadPool (" + n2(used) + " used out of " + n2(total()) + ")";
}
synchronized bool retired() { ret retired; }
synchronized void retire() {
set retired;
for (thread : free) syncNotifyAll(thread); // wake it up so it exits
}
void checkNotRetired {
if (retired()) fail("retired");
}
// We could do a soft-close here (stop the idle threads, let running threads finish, then end those too, stop accepting new orders)
// or a hard close (interrupt all threads, stop accepting new orders)
synchronized close {
retire();
}
}