key = $key; $this->workers = $conf['workers']; $this->maxqueue = $conf['maxqueue']; $this->timeout = $conf['timeout']; } } class PoolCounter_Stub extends PoolCounter { function acquireForMe() { return PoolCounter::LOCKED; } function acquireForAnyone() { return PoolCounter::LOCKED; } function release() { return PoolCounter::RELEASED; } public function __construct() { /* No parameters needed */ } } /** * Handy class for dealing with PoolCounters using class members instead of callbacks. */ abstract class PoolCounterWork { protected $cacheable = false; //Does this override getCachedWork() ? /** * Actually perform the work, caching it if needed. */ abstract function doWork(); /** * Retrieve the work from cache * @return mixed work result or false */ function getCachedWork() { return false; } /** * A work not so good (eg. expired one) but better than an error * message. * @return mixed work result or false */ function fallback() { return false; } /** * Do something with the error, like showing it to the user. */ function error( $status ) { return false; } /** * Get the result of the work (whatever it is), or false. */ function execute( $skipcache = false ) { if ( $this->cacheable && !$skipcache ) { $status = $this->poolCounter->acquireForAnyone(); } else { $status = $this->poolCounter->acquireForMe(); } $result = false; switch ( is_int( $status ) ? $status : PoolCounter::ERROR ) { case PoolCounter::LOCKED: $result = $this->doWork(); $this->poolCounter->release(); return $result; case PoolCounter::DONE: $result = $this->getCachedWork(); if ( $result === false ) { /* That someone else work didn't serve us. * Acquire the lock for me */ return $this->execute( true ); } return $result; case PoolCounter::QUEUE_FULL: case PoolCounter::TIMEOUT: $result = $this->fallback(); if ( $result !== false ) { return $result; } /* no break */ case PoolCounter::ERROR: default: return $this->error( $status ); } } function __construct( $type, $key ) { $this->poolCounter = PoolCounter::factory( $type, $key ); } }