Page MenuHomePhabricator

D21033.diff
No OneTemporary

D21033.diff

diff --git a/src/future/Future.php b/src/future/Future.php
--- a/src/future/Future.php
+++ b/src/future/Future.php
@@ -7,8 +7,6 @@
*/
abstract class Future extends Phobject {
- protected static $handlerInstalled = null;
-
protected $result;
protected $exception;
@@ -37,22 +35,13 @@
'timeout.'));
}
- $wait = $this->getDefaultWait();
- do {
- $this->checkException();
- if ($this->isReady()) {
- break;
- }
-
- $read = $this->getReadSockets();
- $write = $this->getWriteSockets();
+ $graph = new FutureIterator(array($this));
+ $graph->resolveAll();
- if ($read || $write) {
- self::waitForSockets($read, $write, $wait);
- }
- } while (true);
+ if ($this->exception) {
+ throw $this->exception;
+ }
- $this->checkException();
return $this->getResult();
}
@@ -65,17 +54,6 @@
return $this->exception;
}
-
- /**
- * If an exception was set by setException(), throw it.
- */
- private function checkException() {
- if ($this->exception) {
- throw $this->exception;
- }
- }
-
-
/**
* Retrieve a list of sockets which we can wait to become readable while
* a future is resolving. If your future has sockets which can be
@@ -101,56 +79,6 @@
}
- /**
- * Wait for activity on one of several sockets.
- *
- * @param list List of sockets expected to become readable.
- * @param list List of sockets expected to become writable.
- * @param float Timeout, in seconds.
- * @return void
- */
- public static function waitForSockets(
- array $read_list,
- array $write_list,
- $timeout = 1) {
- if (!self::$handlerInstalled) {
- // If we're spawning child processes, we need to install a signal handler
- // here to catch cases like execing '(sleep 60 &) &' where the child
- // exits but a socket is kept open. But we don't actually need to do
- // anything because the SIGCHLD will interrupt the stream_select(), as
- // long as we have a handler registered.
- if (function_exists('pcntl_signal')) {
- if (!pcntl_signal(SIGCHLD, array(__CLASS__, 'handleSIGCHLD'))) {
- throw new Exception(pht('Failed to install signal handler!'));
- }
- }
- self::$handlerInstalled = true;
- }
-
- $timeout_sec = (int)$timeout;
- $timeout_usec = (int)(1000000 * ($timeout - $timeout_sec));
-
- $exceptfds = array();
- $ok = @stream_select(
- $read_list,
- $write_list,
- $exceptfds,
- $timeout_sec,
- $timeout_usec);
-
- if ($ok === false) {
- // Hopefully, means we received a SIGCHLD. In the worst case, we degrade
- // to a busy wait.
- }
- }
-
- public static function handleSIGCHLD($signo) {
- // This function is a dummy, we just need to have some handler registered
- // so that PHP will get interrupted during stream_select(). If we don't
- // register a handler, stream_select() won't fail.
- }
-
-
/**
* Retrieve the final result of the future. This method will be called after
* the future is ready (as per @{method:isReady}) but before results are
diff --git a/src/future/FutureIterator.php b/src/future/FutureIterator.php
--- a/src/future/FutureIterator.php
+++ b/src/future/FutureIterator.php
@@ -63,9 +63,7 @@
* @task basics
*/
public function resolveAll() {
- foreach ($this as $future) {
- $future->resolve();
- }
+ iterator_to_array($this);
}
/**
@@ -246,7 +244,7 @@
}
if ($can_use_sockets) {
- Future::waitForSockets($read_sockets, $write_sockets, $wait_time);
+ $this->waitForSockets($read_sockets, $write_sockets, $wait_time);
} else {
usleep(1000);
}
@@ -324,4 +322,58 @@
}
}
+
+ /**
+ * Wait for activity on one of several sockets.
+ *
+ * @param list List of sockets expected to become readable.
+ * @param list List of sockets expected to become writable.
+ * @param float Timeout, in seconds.
+ * @return void
+ */
+ private function waitForSockets(
+ array $read_list,
+ array $write_list,
+ $timeout = 1.0) {
+
+ static $handler_installed = false;
+
+ if (!$handler_installed) {
+ // If we're spawning child processes, we need to install a signal handler
+ // here to catch cases like execing '(sleep 60 &) &' where the child
+ // exits but a socket is kept open. But we don't actually need to do
+ // anything because the SIGCHLD will interrupt the stream_select(), as
+ // long as we have a handler registered.
+ if (function_exists('pcntl_signal')) {
+ if (!pcntl_signal(SIGCHLD, array(__CLASS__, 'handleSIGCHLD'))) {
+ throw new Exception(pht('Failed to install signal handler!'));
+ }
+ }
+ $handler_installed = true;
+ }
+
+ $timeout_sec = (int)$timeout;
+ $timeout_usec = (int)(1000000 * ($timeout - $timeout_sec));
+
+ $exceptfds = array();
+ $ok = @stream_select(
+ $read_list,
+ $write_list,
+ $exceptfds,
+ $timeout_sec,
+ $timeout_usec);
+
+ if ($ok === false) {
+ // Hopefully, means we received a SIGCHLD. In the worst case, we degrade
+ // to a busy wait.
+ }
+ }
+
+ public static function handleSIGCHLD($signo) {
+ // This function is a dummy, we just need to have some handler registered
+ // so that PHP will get interrupted during "stream_select()". If we don't
+ // register a handler, "stream_select()" won't fail.
+ }
+
+
}

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 28, 1:28 PM (11 h, 40 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6797178
Default Alt Text
D21033.diff (5 KB)

Event Timeline