mirror of
https://github.com/danog/file.git
synced 2025-01-22 13:21:13 +01:00
Add AsyncFileMutex (#43)
This commit is contained in:
parent
01e2a91e34
commit
289a723d5e
@ -31,9 +31,9 @@ before_install:
|
||||
|
||||
install:
|
||||
- if [ "$TRAVIS_PHP_VERSION" = "nightly" ]; then
|
||||
composer update -n --prefer-dist --ignore-platform-reqs;
|
||||
composer update -n --ignore-platform-reqs;
|
||||
else
|
||||
composer update -n --prefer-dist;
|
||||
composer update -n;
|
||||
fi
|
||||
- composer show
|
||||
|
||||
|
@ -35,7 +35,8 @@
|
||||
"php": ">=7.1",
|
||||
"amphp/amp": "^2.2",
|
||||
"amphp/byte-stream": "^1.6.1",
|
||||
"amphp/parallel": "^1.2"
|
||||
"amphp/parallel": "^1.2",
|
||||
"amphp/sync": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-eio": "^2",
|
||||
@ -52,7 +53,13 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Amp\\File\\Test\\": "test"
|
||||
"Amp\\File\\Test\\": "test",
|
||||
"Amp\\Sync\\Test\\": "vendor/amphp/sync/test"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": {
|
||||
"amphp/sync": "source"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
|
84
src/Sync/AsyncFileMutex.php
Normal file
84
src/Sync/AsyncFileMutex.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\File\Sync;
|
||||
|
||||
use Amp\Coroutine;
|
||||
use Amp\Delayed;
|
||||
use Amp\File\FilesystemException;
|
||||
use Amp\Promise;
|
||||
use Amp\Sync\Lock;
|
||||
use Amp\Sync\Mutex;
|
||||
use Amp\Sync\SyncException;
|
||||
use function Amp\File\open;
|
||||
use function Amp\File\unlink;
|
||||
|
||||
final class AsyncFileMutex implements Mutex
|
||||
{
|
||||
private const LATENCY_TIMEOUT = 10;
|
||||
|
||||
/** @var string The full path to the lock file. */
|
||||
private $fileName;
|
||||
|
||||
/**
|
||||
* @param string $fileName Name of temporary file to use as a mutex.
|
||||
*/
|
||||
public function __construct(string $fileName)
|
||||
{
|
||||
$this->fileName = $fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function acquire(): Promise
|
||||
{
|
||||
return new Coroutine($this->doAcquire());
|
||||
}
|
||||
|
||||
/**
|
||||
* @coroutine
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
private function doAcquire(): \Generator
|
||||
{
|
||||
// Try to create the lock file. If the file already exists, someone else
|
||||
// has the lock, so set an asynchronous timer and try again.
|
||||
while (true) {
|
||||
try {
|
||||
$file = yield open($this->fileName, 'x');
|
||||
|
||||
break;
|
||||
} catch (FilesystemException $exception) {
|
||||
yield new Delayed(self::LATENCY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// Return a lock object that can be used to release the lock on the mutex.
|
||||
$lock = new Lock(0, function (): void {
|
||||
$this->release();
|
||||
});
|
||||
|
||||
yield $file->close();
|
||||
|
||||
return $lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the lock on the mutex.
|
||||
*/
|
||||
private function release(): void
|
||||
{
|
||||
unlink($this->fileName)->onResolve(
|
||||
function (?\Throwable $exception): void {
|
||||
if ($exception !== null) {
|
||||
throw new SyncException(
|
||||
'Failed to unlock the mutex file: ' . $this->fileName,
|
||||
0,
|
||||
$exception
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@ final class UvDriver implements Driver
|
||||
|
||||
$openArr = [$mode, $path, $deferred];
|
||||
\uv_fs_open($this->loop, $path, $flags, $chmod, function ($fh) use ($openArr): void {
|
||||
if ($fh) {
|
||||
if (\is_resource($fh)) {
|
||||
$this->onOpenHandle($fh, $openArr);
|
||||
} else {
|
||||
[, $path, $deferred] = $openArr;
|
||||
|
15
test/Sync/AsyncFileMutexTest.php
Normal file
15
test/Sync/AsyncFileMutexTest.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace Amp\File\Test\Sync;
|
||||
|
||||
use Amp\File\Sync\AsyncFileMutex;
|
||||
use Amp\Sync\Mutex;
|
||||
use Amp\Sync\Test\AbstractMutexTest;
|
||||
|
||||
final class AsyncFileMutexTest extends AbstractMutexTest
|
||||
{
|
||||
public function createMutex(): Mutex
|
||||
{
|
||||
return new AsyncFileMutex(\tempnam(\sys_get_temp_dir(), 'mutex-') . '.lock');
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user