public function run() { echo 'Hello, I am a thread with id ' . $this->getPid() . "!\nTrying to lock the critical section\n"; $lock = new GPhpThreadLockGuard($this->criticalSection); echo "=--- locked " . $this->getPid() . "\n"; $this->criticalSection->addOrUpdateResource('IAM', $this->getPid()); $criticalSection2 = new GPhpThreadCriticalSection(); $a = new MyThreadThread($criticalSection2, true); $b = new MyThreadThread($criticalSection2, true); $a->start(); $b->start(); $a->join(); $b->join(); $criticalSection2->lock(); echo "=###= Last internal cs value: " . $criticalSection2->getResourceValue('IAM') . "\n"; $criticalSection2->unlock(); $this->criticalSection->addOrUpdateResource('IAMNOT', '0xdead1'); $this->criticalSection->removeResource('IAMNOT'); echo "=--- unlocked " . $this->getPid() . "\n"; GPhpThread::resetThreadIdGenerator(); $ms2 = new MyStuff('heavy thread 1'); }
/** * Waits for executing thread to return. * @param bool $useBlocking If is set to true will block the until the thread returns. * @return bool True if the thread has joined otherwise false. */ public final function join($useBlocking = true) { // {{{ if (!$this->amIStarted) { return false; } if ($this->amIParent()) { $status = null; $res = 0; if ($useBlocking) { GPhpThread::BGN_HIGH_PRIOR_EXEC_BLOCK(); while (($res = pcntl_waitpid($this->childPid, $status, WNOHANG)) == 0) { GPhpThreadCriticalSection::dispatch(); usleep(mt_rand(10000, 40000)); } if ($res > 0 && pcntl_wifexited($status)) { $this->exitCode = pcntl_wexitstatus($status); } else { $this->exitCode = false; } if ($this->criticalSection !== null) { $this->criticalSection->finalize($this->uniqueId); } $this->childPid = null; $this->_childPid = null; $this->amIStarted = false; GPhpThread::END_HIGH_PRIOR_EXEC_BLOCK(); } else { $res = pcntl_waitpid($this->childPid, $status, WNOHANG); if ($res > 0 && $this->criticalSection !== null) { $this->criticalSection->finalize($this->uniqueId); } if ($res > 0 && pcntl_wifexited($status)) { $this->exitCode = pcntl_wexitstatus($status); if ($this->criticalSection !== null) { $this->criticalSection->finalize($this->uniqueId); } $this->amIStarted = false; } else { if ($res == -1) { $this->exitCode = false; } } if ($res != 0) { if ($this->criticalSection !== null) { $this->criticalSection->finalize($this->uniqueId); } $this->childPid = null; $this->_childPid = null; } } return $res; } if ($this->childPid == -1) { return false; } exit(255); }
// Simple Demonstration how use GPhpThread require_once __DIR__ . '/../GPhpThread.php'; class MyThread extends GPhpThread { public function run() { echo 'Hello, I am a thread with id ' . $this->getPid() . "!\nTrying to lock the critical section\n"; if ($this->criticalSection->lock()) { echo "=--- locked " . $this->getPid() . "\n"; $this->criticalSection->addOrUpdateResource('IAM', $this->getPid()); $this->criticalSection->addOrUpdateResource('IAMNOT', '0xdead1'); $this->criticalSection->removeResource('IAMNOT'); while (!$this->criticalSection->unlock()) { $this->sleep(200000); } echo "=--- unlocked " . $this->getPid() . "\n"; } } } echo "Master main EP " . getmypid() . "\n"; $criticalSection = new GPhpThreadCriticalSection(); $criticalSection->cleanPipeGarbage(); // remove any garbage left from any ungracefully terminated previous executions echo "\nLaunching Thread1...\n\n"; $thr1 = new MyThread($criticalSection, true); $thr2 = new MyThread($criticalSection, true); $thr1->start(); echo "Thread1 pid is: " . $thr1->getPid() . "\n"; $thr2->start(); $thr2->join(); $thr1->join();
{ public function run() { echo 'Hello, I am a thread with id ' . $this->getPid() . "!\nTrying to lock the critical section\n"; if ($this->criticalSection->lock()) { echo "=--- locked " . $this->getPid() . "\n"; $this->criticalSection->addOrUpdateResource('IAM', $this->getPid()); $this->criticalSection->addOrUpdateResource('IAMNOT', '0xdead1'); $this->criticalSection->removeResource('IAMNOT'); $this->criticalSection->unlock(); echo "=--- unlocked " . $this->getPid() . "\n"; } } } echo "Master main EP " . getmypid() . "\n"; $criticalSection = new GPhpThreadCriticalSection(); $criticalSection->cleanPipeGarbage(); // remove any garbage left from any ungracefully terminated previous executions $threadPool = array(); $tpSize = 20; for ($i = 1; $i <= $tpSize; ++$i) { $threadPool[$i] = new MyThread($criticalSection, true); } // xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_NO_BUILTINS); GPhpThread::BGN_HIGH_PRIOR_EXEC_BLOCK(); // this will result fast thread creation but, because of that all threads will try // to reach the critical section at once in some cases may take twice the time for each one in order to lock the critical section for ($i = 1; $i <= $tpSize; ++$i) { $threadPool[$i]->start(); echo "{$i} of {$tpSize} started\n"; }
{ echo 'Hello, I am a thread with id ' . $this->getPid() . "!\nTrying to lock the critical section\n"; if ($this->criticalSection->lock()) { echo "=--- locked " . $this->getPid() . "\n"; $this->criticalSection->addOrUpdateResource('IAM', $this->getPid()); $this->criticalSection->addOrUpdateResource('IAMNOT', '0xdead1'); $this->criticalSection->removeResource('IAMNOT'); while (!$this->criticalSection->unlock()) { $this->sleep(200000); } echo "=--- unlocked " . $this->getPid() . "\n"; } } } echo "Master main EP " . getmypid() . "\n"; $criticalSection = new GPhpThreadCriticalSection(); $criticalSection->cleanPipeGarbage(); // remove any garbage left from any ungracefully terminated previous executions echo "\nLaunching Thread1...\n\n"; $thr1 = new MyThread($criticalSection, true); $thr1->start(); $thr1->join(); echo "\n---Thread1 id was: " . $criticalSection->getResourceValueFast('IAM') . "---\n"; echo "Master after the join of Thread1.\n\n"; echo "\nLaunching Thread2...\n\n"; $thr2 = new MyThread($criticalSection, true); $thr2->start(); $thr2->join(); echo "---Thread2 id was: " . $criticalSection->getResourceValueFast('IAM') . "---\n"; echo "Master after the join of Thread2.\n\n"; echo "\n\nThe resources that left in the critical section:\n";