From 6b75562c3e9b0689cf0828acbf3d9245d50d4807 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 26 Feb 2020 14:11:02 -0800 Subject: [PATCH] Make "exception" on Future a private property Summary: Depends on D21034. Ref T11968. Continue modernizing Future. Test Plan: Ran tests, created a revision. Maniphest Tasks: T11968 Differential Revision: https://secure.phabricator.com/D21035 --- src/future/Future.php | 51 +++++++++++++++++++------- src/future/FutureIterator.php | 67 ++++++++++++++++++----------------- src/future/FutureProxy.php | 30 +++++++++------- 3 files changed, 90 insertions(+), 58 deletions(-) diff --git a/src/future/Future.php b/src/future/Future.php index 08772279..f58a5287 100644 --- a/src/future/Future.php +++ b/src/future/Future.php @@ -9,8 +9,7 @@ abstract class Future extends Phobject { private $hasResult = false; private $result; - - protected $exception; + private $exception; /** * Is this future's process complete? Specifically, can this future be @@ -37,23 +36,34 @@ abstract class Future extends Phobject { 'timeout.')); } - $graph = new FutureIterator(array($this)); - $graph->resolveAll(); + if (!$this->hasResult()) { + $graph = new FutureIterator(array($this)); + $graph->resolveAll(); + } - if ($this->exception) { - throw $this->exception; + if ($this->hasException()) { + throw $this->getException(); } return $this->getResult(); } - public function setException(Exception $ex) { - $this->exception = $ex; - return $this; - } + final public function updateFuture() { + if ($this->hasException()) { + return; + } - public function getException() { - return $this->exception; + if ($this->hasResult()) { + return; + } + + try { + $this->isReady(); + } catch (Exception $ex) { + $this->setException($ex); + } catch (Throwable $ex) { + $this->setException($ex); + } } /** @@ -125,8 +135,23 @@ abstract class Future extends Phobject { return $this; } - final protected function hasResult() { + final public function hasResult() { return $this->hasResult; } + final private function setException($exception) { + // NOTE: The parameter may be an Exception or a Throwable. + $this->exception = $exception; + return $this; + } + + final private function getException() { + return $this->exception; + } + + final public function hasException() { + return ($this->exception !== null); + } + + } diff --git a/src/future/FutureIterator.php b/src/future/FutureIterator.php index 933fe9d8..c8b01294 100644 --- a/src/future/FutureIterator.php +++ b/src/future/FutureIterator.php @@ -180,6 +180,7 @@ final class FutureIterator extends Phobject implements Iterator { $this->isTimeout = false; $check = $this->getWorkingSet(); + $resolve = null; do { $read_sockets = array(); @@ -188,48 +189,49 @@ final class FutureIterator extends Phobject implements Iterator { $wait_time = 1; foreach ($check as $wait => $key) { $future = $this->futures[$key]; - try { - if ($future->getException()) { + + $future->updateFuture(); + + if ($future->hasException()) { + if ($resolve === null) { $resolve = $wait; - continue; - } - if ($future->isReady()) { - if ($resolve === null) { - $resolve = $wait; - } - continue; } + continue; + } - $got_sockets = false; - $socks = $future->getReadSockets(); - if ($socks) { - $got_sockets = true; - foreach ($socks as $socket) { - $read_sockets[] = $socket; - } + if ($future->hasResult()) { + if ($resolve === null) { + $resolve = $wait; } + continue; + } - $socks = $future->getWriteSockets(); - if ($socks) { - $got_sockets = true; - foreach ($socks as $socket) { - $write_sockets[] = $socket; - } + $got_sockets = false; + $socks = $future->getReadSockets(); + if ($socks) { + $got_sockets = true; + foreach ($socks as $socket) { + $read_sockets[] = $socket; } + } - // If any currently active future had neither read nor write sockets, - // we can't wait for the current batch of items using sockets. - if (!$got_sockets) { - $can_use_sockets = false; - } else { - $wait_time = min($wait_time, $future->getDefaultWait()); + $socks = $future->getWriteSockets(); + if ($socks) { + $got_sockets = true; + foreach ($socks as $socket) { + $write_sockets[] = $socket; } - } catch (Exception $ex) { - $this->futures[$key]->setException($ex); - $resolve = $wait; - break; + } + + // If any currently active future had neither read nor write sockets, + // we can't wait for the current batch of items using sockets. + if (!$got_sockets) { + $can_use_sockets = false; + } else { + $wait_time = min($wait_time, $future->getDefaultWait()); } } + if ($resolve === null) { // Check for a setUpdateInterval() timeout. @@ -253,6 +255,7 @@ final class FutureIterator extends Phobject implements Iterator { $this->key = $this->wait[$resolve]; unset($this->wait[$resolve]); + $this->updateWorkingSet(); } diff --git a/src/future/FutureProxy.php b/src/future/FutureProxy.php index 4b90df40..65cbffa2 100644 --- a/src/future/FutureProxy.php +++ b/src/future/FutureProxy.php @@ -27,25 +27,29 @@ abstract class FutureProxy extends Future { } public function isReady() { - return $this->getProxiedFuture()->isReady(); + if ($this->hasResult()) { + return true; + } + + $proxied = $this->getProxiedFuture(); + + $is_ready = $proxied->isReady(); + + if ($proxied->hasResult()) { + $result = $proxied->getResult(); + $result = $this->didReceiveResult($result); + $this->setResult($result); + } + + return $is_ready; } public function resolve() { - $result = $this->getProxiedFuture()->resolve(); - $result = $this->didReceiveResult($result); - $this->setResult($result); + $this->getProxiedFuture()->resolve(); + $this->isReady(); return $this->getResult(); } - public function setException(Exception $ex) { - $this->getProxiedFuture()->setException($ex); - return $this; - } - - public function getException() { - return $this->getProxiedFuture()->getException(); - } - public function getReadSockets() { return $this->getProxiedFuture()->getReadSockets(); }