88 lines
1.6 KiB
PHP
88 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace NoccyLabs\Ipc\Lock;
|
|
|
|
/**
|
|
* Simple filesystem-based lock
|
|
*
|
|
*
|
|
*/
|
|
class FileLock
|
|
{
|
|
const DEFAULT_TIMEOUT = 5;
|
|
|
|
protected $pathname;
|
|
|
|
protected $resource;
|
|
|
|
protected $locked = false;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $pathname
|
|
*/
|
|
public function __construct(string $pathname)
|
|
{
|
|
if (!file_exists($pathname)) {
|
|
throw new \RuntimeException(sprintf(
|
|
"The file %s does not exist",
|
|
$pathname
|
|
));
|
|
}
|
|
|
|
$this->pathname = $pathname;
|
|
$this->resource = fopen($pathname, "r");
|
|
}
|
|
|
|
public function __destruct()
|
|
{
|
|
$this->release();
|
|
fclose($this->resource);
|
|
}
|
|
|
|
/**
|
|
* Acquire an exclusive lock
|
|
*
|
|
* @param float $timeout
|
|
* @return boolean
|
|
*/
|
|
public function acquire(float $timeout = self::DEFAULT_TIMEOUT):bool
|
|
{
|
|
if ($this->locked) {
|
|
return true;
|
|
}
|
|
|
|
$expire = microtime(true) + $timeout;
|
|
while (!flock($this->resource, LOCK_EX|LOCK_NB)) {
|
|
if (microtime(true)>$expire) {
|
|
return false;
|
|
}
|
|
usleep(1000);
|
|
}
|
|
|
|
$this->locked = true;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Release an acquired lock
|
|
*
|
|
* @return void
|
|
*/
|
|
public function release()
|
|
{
|
|
flock($this->resource, LOCK_UN);
|
|
$this->locked = false;
|
|
}
|
|
|
|
/**
|
|
* Check if the lock is acquired
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isLocked():bool
|
|
{
|
|
return $this->locked;
|
|
}
|
|
} |