/** * Attempts to acquire the lock and sleeps for a time if the lock could not be acquired. * * @return \Generator */ public function acquire() : \Generator { $tsl = function () { return $this->lock ? $this->lock = false : true; }; while (!$this->lock || $this->synchronized($tsl)) { yield from Coroutine\sleep(self::LATENCY_TIMEOUT); } return new Lock(function () { $this->release(); }); }
/** * {@inheritdoc} */ public function acquire() : \Generator { // Try to create the lock file. If the file already exists, someone else // has the lock, so set an asynchronous timer and try again. while (($handle = @fopen($this->fileName, 'x')) === false) { yield from Coroutine\sleep(self::LATENCY_TIMEOUT); } // Return a lock object that can be used to release the lock on the mutex. $lock = new Lock(function (Lock $lock) { $this->release(); }); fclose($handle); return $lock; }
/** * Uses a double locking mechanism to acquire a lock without blocking. A * synchronous mutex is used to make sure that the semaphore is queried one * at a time to preserve the integrity of the semaphore itself. Then a lock * count is used to check if a lock is available without blocking. * * If a lock is not available, we add the request to a queue and set a timer * to check again in the future. */ public function acquire() : \Generator { $tsl = function () { // If there are no locks available or the wait queue is not empty, // we need to wait our turn to acquire a lock. if ($this->locks > 0) { --$this->locks; return false; } return true; }; while ($this->locks < 1 || $this->synchronized($tsl)) { yield from Coroutine\sleep(self::LATENCY_TIMEOUT); } return new Lock(function () { $this->release(); }); }
/** * {@inheritdoc} */ public function acquire() { do { // Attempt to acquire a lock from the semaphore. if (@msg_receive($this->queue, 0, $type, 1, $chr, false, MSG_IPC_NOWAIT, $errno)) { // A free lock was found, so resolve with a lock object that can // be used to release the lock. yield new Lock(function (Lock $lock) { $this->release(); }); return; } // Check for unusual errors. if ($errno !== MSG_ENOMSG) { throw new SemaphoreException('Failed to acquire a lock.'); } } while (yield Coroutine\sleep(self::LATENCY_TIMEOUT)); }
}); Coroutine\create(function () { // Create a new child thread that does some blocking stuff. $context = Thread::spawn(function () { printf("\$this: %s\n", get_class($this)); printf("Received the following from parent: %s\n", (yield $this->receive())); print "Sleeping for 3 seconds...\n"; sleep(3); // Blocking call in thread. yield $this->send('Data sent from child.'); print "Sleeping for 2 seconds...\n"; sleep(2); // Blocking call in thread. yield 42; }); print "Waiting 2 seconds to send start data...\n"; yield Coroutine\sleep(2); yield $context->send('Start data'); printf("Received the following from child: %s\n", (yield $context->receive())); printf("Thread ended with value %d!\n", (yield $context->join())); })->cleanup([$timer, 'stop'])->done(); Loop\run();