Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14109096
D21033.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D21033.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21033: Resolve all futures inside FutureIterator
Attached
Detach File
Event Timeline
Log In to Comment