1
0
mirror of https://github.com/danog/file.git synced 2024-11-26 11:54:54 +01:00

Return same promise on subsequent close calls

This commit is contained in:
Aaron Piotrowski 2017-06-22 10:18:55 -05:00
parent 20261f7b77
commit 2ce32d57ff
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
4 changed files with 66 additions and 15 deletions

View File

@ -10,16 +10,36 @@ use Amp\Success;
use function Amp\call; use function Amp\call;
class EioHandle implements Handle { class EioHandle implements Handle {
/** @var \Amp\File\Internal\EioPoll */
private $poll; private $poll;
/** @var resource eio file handle. */
private $fh; private $fh;
/** @var string */
private $path; private $path;
/** @var string */
private $mode; private $mode;
/** @var int */
private $size; private $size;
/** @var int */
private $position; private $position;
/** @var \SplQueue */
private $queue; private $queue;
/** @var bool */
private $isActive = false; private $isActive = false;
/** @var bool */
private $writable = true; private $writable = true;
/** @var \Amp\Promise|null */
private $closing;
public function __construct(Internal\EioPoll $poll, $fh, string $path, string $mode, int $size) { public function __construct(Internal\EioPoll $poll, $fh, string $path, string $mode, int $size) {
$this->poll = $poll; $this->poll = $poll;
$this->fh = $fh; $this->fh = $fh;
@ -169,8 +189,12 @@ class EioHandle implements Handle {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise {
if ($this->closing) {
return $this->closing;
}
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($this->closing = $deferred->promise());
\eio_close($this->fh, \EIO_PRI_DEFAULT, [$this, "onClose"], $deferred); \eio_close($this->fh, \EIO_PRI_DEFAULT, [$this, "onClose"], $deferred);

View File

@ -112,7 +112,7 @@ class FileTask extends BlockingDriver implements Task {
case "fclose": case "fclose":
$file->close(); $file->close();
$environment->delete($this->id); $environment->delete($this->id);
return true; return;
default: default:
throw new \Error('Invalid operation'); throw new \Error('Invalid operation');

View File

@ -40,6 +40,9 @@ class ParallelHandle implements Handle {
/** @var bool */ /** @var bool */
private $writable = true; private $writable = true;
/** @var \Amp\Promise|null */
private $closing;
/** /**
* @param \Amp\Parallel\Worker\Worker $worker * @param \Amp\Parallel\Worker\Worker $worker
* @param int $id * @param int $id
@ -73,20 +76,20 @@ class ParallelHandle implements Handle {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise {
if (!$this->writable) { if ($this->closing) {
return new Success; return $this->closing;
} }
$this->writable = false; $this->writable = false;
if ($this->worker->isRunning()) { if ($this->worker->isRunning()) {
$promise = $this->worker->enqueue(new Internal\FileTask('fclose', [], $this->id)); $this->closing = $this->worker->enqueue(new Internal\FileTask('fclose', [], $this->id));
$this->id = null; $this->id = null;
return $promise; } else {
$this->closing = new Success;
} }
// FIXME: Should that really return new Success instead of an exception? return $this->closing;
return new Success;
} }
/** /**

View File

@ -12,18 +12,39 @@ use Amp\Success;
use function Amp\call; use function Amp\call;
class UvHandle implements Handle { class UvHandle implements Handle {
/** @var UvPoll */
private $poll; private $poll;
private $driver;
private $fh; /** @var \UVLoop */
private $path;
private $mode;
private $size;
private $loop; private $loop;
/** @var resource */
private $fh;
/** @var string */
private $path;
/** @var string */
private $mode;
/** @var int */
private $size;
/** @var int */
private $position; private $position;
/** @var \SplQueue */
private $queue; private $queue;
/** @var bool */
private $isActive = false; private $isActive = false;
/** @var bool */
private $writable = true; private $writable = true;
/** @var \Amp\Promise|null */
private $closing;
/** /**
* @param \Amp\Loop\UvDriver $driver * @param \Amp\Loop\UvDriver $driver
* @param UvPoll $poll Poll for keeping the loop active. * @param UvPoll $poll Poll for keeping the loop active.
@ -33,7 +54,6 @@ class UvHandle implements Handle {
* @param int $size * @param int $size
*/ */
public function __construct(Loop\UvDriver $driver, UvPoll $poll, $fh, string $path, string $mode, int $size) { public function __construct(Loop\UvDriver $driver, UvPoll $poll, $fh, string $path, string $mode, int $size) {
$this->driver = $driver;
$this->poll = $poll; $this->poll = $poll;
$this->fh = $fh; $this->fh = $fh;
$this->path = $path; $this->path = $path;
@ -219,8 +239,12 @@ class UvHandle implements Handle {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise {
if ($this->closing) {
return $this->closing;
}
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($this->closing = $deferred->promise());
\uv_fs_close($this->loop, $this->fh, function ($fh) use ($deferred) { \uv_fs_close($this->loop, $this->fh, function ($fh) use ($deferred) {
// FIXME: Check for errors // FIXME: Check for errors