2016-08-21 23:40:48 -05:00
|
|
|
<?php declare(strict_types = 1);
|
2015-08-07 15:32:18 -05:00
|
|
|
|
2016-08-23 16:47:40 -05:00
|
|
|
namespace Amp\Parallel\Sync;
|
2016-08-18 11:04:48 -05:00
|
|
|
|
2016-08-23 16:47:40 -05:00
|
|
|
use Amp\Parallel\LockAlreadyReleasedError;
|
2015-08-07 15:32:18 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A handle on an acquired lock from a synchronization object.
|
|
|
|
*
|
|
|
|
* This object is not thread-safe; after acquiring a lock from a mutex or
|
|
|
|
* semaphore, the lock should reside in the same thread or process until it is
|
|
|
|
* released.
|
|
|
|
*/
|
2016-08-18 11:04:48 -05:00
|
|
|
class Lock {
|
2016-08-26 10:10:03 -05:00
|
|
|
/** @var callable The function to be called on release. */
|
2015-08-07 15:32:18 -05:00
|
|
|
private $releaser;
|
|
|
|
|
2016-08-26 10:10:03 -05:00
|
|
|
/** @var bool Indicates if the lock has been released. */
|
2015-08-27 12:52:05 -05:00
|
|
|
private $released = false;
|
2015-08-07 15:32:18 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new lock permit object.
|
|
|
|
*
|
|
|
|
* @param callable<Lock> $releaser A function to be called upon release.
|
|
|
|
*/
|
2016-08-18 11:04:48 -05:00
|
|
|
public function __construct(callable $releaser) {
|
2015-08-07 15:32:18 -05:00
|
|
|
$this->releaser = $releaser;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the lock has already been released.
|
|
|
|
*
|
|
|
|
* @return bool True if the lock has already been released, otherwise false.
|
|
|
|
*/
|
2016-08-18 11:04:48 -05:00
|
|
|
public function isReleased(): bool {
|
2015-08-07 15:32:18 -05:00
|
|
|
return $this->released;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Releases the lock.
|
|
|
|
*
|
2015-08-30 17:52:00 -05:00
|
|
|
* @throws LockAlreadyReleasedError If the lock was already released.
|
2015-08-07 15:32:18 -05:00
|
|
|
*/
|
2016-08-18 11:04:48 -05:00
|
|
|
public function release() {
|
2015-08-07 15:32:18 -05:00
|
|
|
if ($this->released) {
|
2015-08-09 22:30:11 -05:00
|
|
|
throw new LockAlreadyReleasedError('The lock has already been released!');
|
2015-08-07 15:32:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke the releaser function given to us by the synchronization source
|
|
|
|
// to release the lock.
|
2016-01-23 00:00:56 -06:00
|
|
|
($this->releaser)($this);
|
2015-08-07 15:32:18 -05:00
|
|
|
$this->released = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Releases the lock when there are no more references to it.
|
|
|
|
*/
|
2016-08-18 11:04:48 -05:00
|
|
|
public function __destruct() {
|
2015-08-07 15:32:18 -05:00
|
|
|
if (!$this->released) {
|
|
|
|
$this->release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|