1
0
mirror of https://github.com/danog/parallel.git synced 2024-12-13 09:37:26 +01:00
parallel/src/Semaphore.php
2015-08-01 21:51:45 -05:00

113 lines
2.7 KiB
PHP

<?php
namespace Icicle\Concurrent;
use Icicle\Concurrent\Exception\SemaphoreException;
use Icicle\Concurrent\Sync\SemaphoreInterface;
/**
* A synchronous semaphore that uses System V IPC semaphores.
*/
class Semaphore implements SemaphoreInterface, \Serializable
{
/**
* @var int The key to the semaphore.
*/
private $key;
/**
* @var int The maximum number of locks.
*/
private $maxLocks;
/**
* @var resource An open handle to the semaphore.
*/
private $handle;
/**
* Creates a new semaphore.
*
* @param int $maxLocks The maximum number of processes that can lock the semaphore.
* @param int $permissions Permissions to access the semaphore.
*/
public function __construct($maxLocks = 1, $permissions = 0666)
{
$this->key = abs(crc32(spl_object_hash($this)));
$this->maxLocks = $maxLocks;
$this->handle = sem_get($this->key, $maxLocks, $permissions, 1);
if ($this->handle === false) {
throw new SemaphoreException('Failed to create the semaphore.');
}
}
/**
* Gets the maximum number of locks.
*
* @return int The maximum number of locks.
*/
public function getMaxLocks()
{
return $this->maxLocks;
}
/**
* Acquires a lock from the semaphore.
*
* Blocks until a lock can be acquired.
*/
public function acquire()
{
if (!sem_acquire($this->handle)) {
throw new SemaphoreException('Failed to lock the semaphore.');
}
}
/**
* Releases a lock to the semaphore.
*/
public function release()
{
if (!sem_release($this->handle)) {
throw new SemaphoreException('Failed to unlock the semaphore.');
}
}
/**
* Removes the semaphore if it still exists.
*/
public function destroy()
{
if (!@sem_remove($this->handle)) {
$error = error_get_last();
if ($error['type'] !== E_WARNING) {
throw new SemaphoreException('Failed to remove the 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, 0666, 1);
}
}