Example class to demonstrate usage of Pool/Worker mechanism, also to show a few tricks & hints ;)
protected functioninc(){++$this->val;}// protected synchronizes by-objectpublic functioninc2(){++$this->val2;}// no synchronization}
classWorkerClassextendsWorker{
protected static$worker_id_next= -1;
protected$worker_id;
protected$config;
public function__construct($config){$this->worker_id= ++static::$worker_id_next;// static members are not avalable in thread but are in 'main thread'$this->config=$config;
}
public functionrun(){
global$config;$config=$this->config;// NOTE: setting by reference WON'T workglobal$worker_id;$worker_id=$this->worker_id;
echo"working context{$worker_id}is created!\n";//$this->say_config(); // globally synchronized function.}
protected functionsay_config(){// 'protected' is synchronized by-object so WON'T work between multiple instancesglobal$config;// you can use the shared $config object as synchronization source.$config->synchronized(function() use (&$config){// NOTE: you can use Closures here, but if you attach a Closure to a Threaded object it will be destroyed as can't be serializedvar_dump($config);
});
}
}
classTaskextendsStackable{// Stackable still exists, it's just somehow dissappeared from docs (probably by mistake). See older version's docs for more details.protected$set;
public function__construct($set){$this->set=$set;
}
public functionrun(){
global$worker_id;
echo"task is running in{$worker_id}!\n";usleep(mt_rand(1,100)*100);$config=$this->getConfig();$val=$config->arr->shift();$config->arr[] =$this->set;
for ($i=0;$i<1000; ++$i){$config->inc();$config->inc2();
}
}
public functiongetConfig(){
global$config;// WorkerClass set this on thread's scope, can be reused by Tasks for additional asynch data source. (ie: connection pool or taskqueue to demultiplexer)return$config;
}
}$config= newConfig;$config->arr= new \Threaded();$config->arr->merge(array(1,2,3,4,5,6));
classPoolClassextendsPool{
public functionworker_list(){
if ($this->workers!==null)
returnarray_keys($this->workers);
returnnull;
}
}$pool= newPoolClass(3,'WorkerClass', [$config] );$pool->worker_list();//$pool->submitTo(0,new Task(-10)); // submitTo DOES NOT try to create worker$spammed_id= -1;
for ($i=1;$i<=100; ++$i){// add some jobsif ($spammed_id== -1&& ($x=$pool->worker_list())!=null&& @$x[2]){$spammed_id=$x[2];
echo"spamming worker{$spammed_id}with lots of tasks from now on\n";
}
if ($spammed_id!= -1&& ($i%5) ==0)// every 5th job is routed to one worker, so it has 20% of the total jobs (with 3 workers it should do ~33%, not it has (33+20)%, so only delegate to worker if you plan to do balancing as well... )$pool->submitTo($spammed_id,newTask(10*$i));
else$pool->submit(newTask(10*$i));
}$pool->shutdown();var_dump($config);// "val" is exactly 100000, "val2" is probably a bit less
// also: if you disable the spammer, you'll that the order of the "arr" is random.?>