1
0
mirror of https://github.com/danog/parallel.git synced 2024-11-26 20:34:40 +01:00

Semaphore handles can be serialized across contexts

This commit is contained in:
coderstephen 2015-07-10 16:17:18 -05:00
parent 2c40e0ddcb
commit 8dd597238d

View File

@ -1,33 +1,53 @@
<?php <?php
namespace Icicle\Concurrent; namespace Icicle\Concurrent;
use Icicle\Concurrent\Exception\SemaphoreException;
/** /**
* A synchronous semaphore that uses System V IPC semaphores. * A synchronous semaphore that uses System V IPC semaphores.
*/ */
class Semaphore class Semaphore implements \Serializable
{ {
/**
* @var int The key to the semaphore.
*/
private $key; private $key;
private $identifier;
/**
* @var int The maximum number of locks.
*/
private $maxLocks;
/**
* @var resource An open handle to the semaphore.
*/
private $handle;
/** /**
* Creates a new semaphore. * Creates a new semaphore.
* *
* @param int $max The maximum number of processes that can lock the semaphore. * @param int $maxLocks The maximum number of processes that can lock the semaphore.
* @param int $permissions Permissions to access the semaphore. * @param int $permissions Permissions to access the semaphore.
*/ */
public function __construct($max = 1, $permissions = 0666) public function __construct($maxLocks = 1, $permissions = 0666)
{ {
$this->key = abs(crc32(spl_object_hash($this))); $this->key = abs(crc32(spl_object_hash($this)));
$this->identifier = sem_get($this->key, $max, $permissions); $this->maxLocks = $maxLocks;
$this->handle = sem_get($this->key, $maxLocks, $permissions, 0);
if ($this->identifier === false) { if ($this->handle === false) {
throw new SemaphoreException('Failed to create the semaphore.'); throw new SemaphoreException('Failed to create the semaphore.');
} }
} }
public function __destruct() /**
* Gets the maximum number of locks.
*
* @return int The maximum number of locks.
*/
public function getMaxLocks()
{ {
$this->remove(); return $this->maxLocks;
} }
/** /**
@ -37,7 +57,7 @@ class Semaphore
*/ */
public function lock() public function lock()
{ {
if (!sem_acquire($this->identifier)) { if (!sem_acquire($this->handle)) {
throw new SemaphoreException('Failed to lock the semaphore.'); throw new SemaphoreException('Failed to lock the semaphore.');
} }
} }
@ -47,7 +67,7 @@ class Semaphore
*/ */
public function unlock() public function unlock()
{ {
if (!sem_release($this->identifier)) { if (!sem_release($this->handle)) {
throw new SemaphoreException('Failed to unlock the semaphore.'); throw new SemaphoreException('Failed to unlock the semaphore.');
} }
} }
@ -55,9 +75,9 @@ class Semaphore
/** /**
* Removes the semaphore if it still exists. * Removes the semaphore if it still exists.
*/ */
public function remove() public function destroy()
{ {
if (!@sem_remove($this->identifier)) { if (!@sem_remove($this->handle)) {
$error = error_get_last(); $error = error_get_last();
if ($error['type'] !== E_WARNING) { if ($error['type'] !== E_WARNING) {
@ -65,4 +85,27 @@ class Semaphore
} }
} }
} }
/**
* Serializes the semaphore.
*
* @return string The serialized semaphore.
*/
public function serialize()
{
return serialize([$this->key, $this->maxLocks]);
}
/**
* Unserializes a serialized semaphore.
*
* @param string $serialized The serialized semaphore.
*/
public function unserialize($serialized)
{
// Get the semaphore key and attempt to re-connect to the semaphore in
// memory.
list($this->key, $this->maxLocks) = unserialize($serialized);
$this->handle = sem_get($this->key, $maxLocks);
}
} }