44 lines
1.3 KiB
PHP
44 lines
1.3 KiB
PHP
<?php
|
|
|
|
namespace WP_Ultimo\Dependencies\Amp\Sync;
|
|
|
|
use WP_Ultimo\Dependencies\Amp\CallableMaker;
|
|
use WP_Ultimo\Dependencies\Amp\Deferred;
|
|
use WP_Ultimo\Dependencies\Amp\Promise;
|
|
use WP_Ultimo\Dependencies\Amp\Success;
|
|
class LocalSemaphore implements Semaphore
|
|
{
|
|
use CallableMaker;
|
|
// kept for BC only
|
|
/** @var int[] */
|
|
private $locks;
|
|
/** @var Deferred[] */
|
|
private $queue = [];
|
|
public function __construct(int $maxLocks)
|
|
{
|
|
if ($maxLocks < 1) {
|
|
throw new \Error('The number of locks must be greater than 0');
|
|
}
|
|
$this->locks = \range(0, $maxLocks - 1);
|
|
}
|
|
/** {@inheritdoc} */
|
|
public function acquire() : Promise
|
|
{
|
|
if (!empty($this->locks)) {
|
|
return new Success(new Lock(\array_shift($this->locks), \Closure::fromCallable([$this, 'release'])));
|
|
}
|
|
$this->queue[] = $deferred = new Deferred();
|
|
return $deferred->promise();
|
|
}
|
|
private function release(Lock $lock) : void
|
|
{
|
|
$id = $lock->getId();
|
|
if (!empty($this->queue)) {
|
|
$deferred = \array_shift($this->queue);
|
|
$deferred->resolve(new Lock($id, \Closure::fromCallable([$this, 'release'])));
|
|
return;
|
|
}
|
|
$this->locks[] = $id;
|
|
}
|
|
}
|