Add portable mutex using flock()

This commit is contained in:
coderstephen
2015-08-01 21:07:33 -05:00
parent eded7b86a4
commit cf788a9377
2 changed files with 91 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
<?php
namespace Icicle\Concurrent\Exception;
class MutexException extends Exception
{
}

85
src/Sync/FileMutex.php Normal file
View File

@@ -0,0 +1,85 @@
<?php
namespace Icicle\Concurrent\Sync;
use Icicle\Concurrent\Exception\MutexException;
/**
* A cross-platform mutex that uses file locking as the lock mechanism.
*
* This mutex implementation is not always atomic and depends on the operating
* system's implementation of file locking operations. Use this implementation
* only if no other mutex types are available.
*
* @see http://php.net/manual/en/function.flock.php
*/
class FileMutex implements MutexInterface
{
/**
* @var string The full path to the lock file.
*/
private $fileName;
/**
* Creates a new mutex.
*/
public function __construct()
{
$this->fileName = sys_get_temp_dir()
. DIRECTORY_SEPARATOR
. spl_object_hash($this)
. '.lock';
touch($this->fileName, time());
}
/**
* {@inheritdoc}
*/
public function lock()
{
$handle = $this->getFileHandle();
$success = flock($handle, LOCK_EX);
fclose($handle);
if (!$success) {
throw new MutexException("Failed to access the mutex file for locking.")
}
}
/**
* {@inheritdoc}
*/
public function unlock()
{
$handle = $this->getFileHandle();
$success = flock($handle, LOCK_UN);
fclose($handle);
if (!$success) {
throw new MutexException("Failed to unlock the mutex file.")
}
}
/**
* Destroys the mutex.
*/
public function __destruct()
{
@unlink($this->fileName);
}
/**
* Opens the mutex file and returns a file resource.
*
* @return resource
*/
private function getFileHandle()
{
$handle = @fopen($this->fileName, 'wb');
if ($handle === false) {
throw new MutexException("Failed to open the mutex file.");
}
return $handle;
}
}