163 lines
3.1 KiB
PHP
163 lines
3.1 KiB
PHP
<?php
|
|
/**
|
|
* Created by PhpStorm.
|
|
* User: Jenner
|
|
* Date: 2015/8/12
|
|
* Time: 20:52
|
|
*/
|
|
|
|
namespace Jenner\SimpleFork\Lock;
|
|
|
|
|
|
/**
|
|
* sem lock
|
|
*
|
|
* @package Jenner\SimpleFork\Lock
|
|
*/
|
|
class Semaphore implements LockInterface
|
|
{
|
|
/**
|
|
* @var
|
|
*/
|
|
private $lock_id;
|
|
/**
|
|
* @var bool
|
|
*/
|
|
private $locked = false;
|
|
|
|
/**
|
|
* init a lock
|
|
*
|
|
* @param $key
|
|
* @param $count
|
|
* @throws \RuntimeException
|
|
*/
|
|
private function __construct($key, $count = 1)
|
|
{
|
|
if (($this->lock_id = sem_get($this->_stringToSemKey($key), $count)) === false) {
|
|
throw new \RuntimeException("Cannot create semaphore for key: {$key}");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Semaphore requires a numeric value as the key
|
|
*
|
|
* @param $identifier
|
|
* @return int
|
|
*/
|
|
protected function _stringToSemKey($identifier)
|
|
{
|
|
$md5 = md5($identifier);
|
|
$key = 0;
|
|
for ($i = 0; $i < 32; $i++) {
|
|
$key += ord($md5{$i}) * $i;
|
|
}
|
|
return $key;
|
|
}
|
|
|
|
/**
|
|
* create a lock instance
|
|
*
|
|
* @param $key
|
|
* @return Semaphore
|
|
*/
|
|
public static function create($key)
|
|
{
|
|
return new Semaphore($key);
|
|
}
|
|
|
|
/**
|
|
* release lock
|
|
*
|
|
* @throws \RuntimeException
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
if ($this->isLocked()) {
|
|
$this->release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* is locked
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isLocked()
|
|
{
|
|
return $this->locked === true ? true : false;
|
|
}
|
|
|
|
/**
|
|
* release lock
|
|
*
|
|
* @return bool
|
|
* @throws \RuntimeException
|
|
*/
|
|
public function release()
|
|
{
|
|
if (!$this->locked) {
|
|
throw new \RuntimeException("release a non lock");
|
|
}
|
|
|
|
if (!sem_release($this->lock_id)) {
|
|
return false;
|
|
}
|
|
$this->locked = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* get a lock
|
|
*
|
|
* @param bool $blocking
|
|
* @return bool
|
|
*/
|
|
public function acquire($blocking = true)
|
|
{
|
|
if ($this->locked) {
|
|
throw new \RuntimeException('already lock by yourself');
|
|
}
|
|
|
|
if ($blocking === false) {
|
|
if (version_compare(PHP_VERSION, '5.6.0') < 0) {
|
|
throw new \RuntimeException('php version is at least 5.6.0 for param blocking');
|
|
}
|
|
if (!sem_acquire($this->lock_id, true)) {
|
|
return false;
|
|
}
|
|
$this->locked = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
if (!sem_acquire($this->lock_id)) {
|
|
return false;
|
|
}
|
|
$this->locked = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* remove the semaphore resource
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function remove()
|
|
{
|
|
if ($this->locked) {
|
|
throw new \RuntimeException('can not remove a locked semaphore resource');
|
|
}
|
|
if (!is_resource($this->lock_id)) {
|
|
throw new \RuntimeException('can not remove a empty semaphore resource');
|
|
}
|
|
|
|
if (!sem_release($this->lock_id)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} |