Skip to content

Instantly share code, notes, and snippets.

@dfeyer
Last active February 16, 2016 19:19
Show Gist options
  • Save dfeyer/9aacf929e658373b83b7 to your computer and use it in GitHub Desktop.
Save dfeyer/9aacf929e658373b83b7 to your computer and use it in GitHub Desktop.
Semaphore based lock strategy for Flow Framework
<?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