Last active
February 16, 2016 19:19
-
-
Save dfeyer/9aacf929e658373b83b7 to your computer and use it in GitHub Desktop.
Semaphore based lock strategy for Flow Framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace TYPO3\Flow\Utility\Lock; | |
/* | |
* This file is part of the TYPO3.Flow package. | |
* | |
* (c) Contributors of the Neos Project - www.neos.io | |
* | |
* This package is Open Source Software. For the full copyright and license | |
* information, please view the LICENSE file which was distributed with this | |
* source code. | |
*/ | |
use TYPO3\Flow\Annotations as Flow; | |
use TYPO3\Flow\Core\Bootstrap; | |
use TYPO3\Flow\Utility\Exception\LockNotAcquiredException; | |
use TYPO3\Flow\Utility\Files; | |
/** | |
* A Semaphore based lock strategy. | |
* | |
* This lock strategy is based on Sempahore. | |
* | |
* @see http://php.net/manual/fr/ref.sem.php | |
* | |
* @Flow\Scope("prototype") | |
*/ | |
class SemaphoreLockStrategy implements LockStrategyInterface | |
{ | |
const READ_ACCESS = 0; | |
const WRITE_ACCESS = 1; | |
/** | |
* Mutex semaphore | |
* | |
* @var resource | |
*/ | |
protected $mutex; | |
/** | |
* Read/write semaphore | |
* | |
* @var resource | |
*/ | |
protected $resource; | |
/** | |
* @var integer | |
*/ | |
protected $writers = 0; | |
/** | |
* @var integer | |
*/ | |
protected $readers = 0; | |
/** | |
* @var boolean | |
*/ | |
protected $exclusiveLock; | |
/** | |
* @param string $subject | |
* @param boolean $exclusiveLock TRUE to, acquire an exclusive (write) lock, FALSE for a shared (read) lock. | |
* @return void | |
*/ | |
public function acquire($subject, $exclusiveLock) | |
{ | |
$mutexKey = crc32($subject . ':mutex'); | |
$resourceKey = crc32($subject . ':resource'); | |
$this->mutex = sem_get($mutexKey, 1); | |
$this->resource = sem_get($resourceKey, 1); | |
$this->exclusiveLock = $exclusiveLock; | |
$this->requestAccess($this->getAccessMode()); | |
} | |
/** | |
* @return boolean TRUE on success, FALSE otherwise | |
*/ | |
public function release() | |
{ | |
$this->requestRelease($this->getAccessMode()); | |
} | |
/** | |
* @return integer | |
*/ | |
protected function getAccessMode() | |
{ | |
return $this->exclusiveLock ? self::WRITE_ACCESS : self::READ_ACCESS; | |
} | |
/** | |
* Request acess to the resource | |
* | |
* @param integer $accessType | |
* @return void | |
*/ | |
protected function requestAccess($accessType = self::READ_ACCESS) | |
{ | |
if ($accessType == self::WRITE_ACCESS) { | |
sem_acquire($this->mutex); | |
$this->writers++; | |
sem_release($this->mutex); | |
sem_acquire($this->resource); | |
} else { | |
sem_acquire($this->mutex); | |
if ($this->writers > 0 || $this->readers === 0) { | |
sem_release($this->mutex); | |
sem_acquire($this->resource); | |
sem_acquire($this->mutex); | |
} | |
$this->readers++; | |
sem_release($this->mutex); | |
} | |
} | |
/** | |
* @param integer $accessType | |
*/ | |
protected function requestRelease($accessType = self::READ_ACCESS) | |
{ | |
if ($accessType == self::WRITE_ACCESS) { | |
sem_acquire($this->mutex); | |
$this->writers--; | |
sem_release($this->mutex); | |
@sem_release($this->resource); | |
} else { | |
sem_acquire($this->mutex); | |
$this->readers--; | |
if ($this->readers === 0) { | |
sem_release($this->resource); | |
} | |
sem_release($this->mutex); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment