Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15448210
D21034.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D21034.id.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,7 +7,9 @@
*/
abstract class Future extends Phobject {
- protected $result;
+ private $hasResult = false;
+ private $result;
+
protected $exception;
/**
@@ -79,22 +81,6 @@
}
- /**
- * 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
- * passed back to the caller. The major use of this function is that you can
- * override it in subclasses to do postprocessing or error checking, which is
- * particularly useful if building application-specific futures on top of
- * primitive transport futures (like @{class:CurlFuture} and
- * @{class:ExecFuture}) which can make it tricky to hook this logic into the
- * main pipeline.
- *
- * @return mixed Final resolution of this future.
- */
- protected function getResult() {
- return $this->result;
- }
-
/**
* Default amount of time to wait on stream select for this future. Normally
* 1 second is fine, but if the future has a timeout sooner than that it
@@ -109,4 +95,38 @@
return $this;
}
+ /**
+ * Retrieve the final result of the future.
+ *
+ * @return wild Final resolution of this future.
+ */
+ final protected function getResult() {
+ if (!$this->hasResult()) {
+ throw new Exception(
+ pht(
+ 'Future has not yet resolved. Resolve futures before retrieving '.
+ 'results.'));
+ }
+
+ return $this->result;
+ }
+
+ final protected function setResult($result) {
+ if ($this->hasResult()) {
+ throw new Exception(
+ pht(
+ 'Future has already resolved. Futures may not resolve more than '.
+ 'once.'));
+ }
+
+ $this->hasResult = true;
+ $this->result = $result;
+
+ return $this;
+ }
+
+ final protected function hasResult() {
+ return $this->hasResult;
+ }
+
}
diff --git a/src/future/FutureProxy.php b/src/future/FutureProxy.php
--- a/src/future/FutureProxy.php
+++ b/src/future/FutureProxy.php
@@ -31,7 +31,9 @@
}
public function resolve() {
- $this->getProxiedFuture()->resolve();
+ $result = $this->getProxiedFuture()->resolve();
+ $result = $this->didReceiveResult($result);
+ $this->setResult($result);
return $this->getResult();
}
@@ -52,15 +54,6 @@
return $this->getProxiedFuture()->getWriteSockets();
}
- protected function getResult() {
- if ($this->result === null) {
- $result = $this->getProxiedFuture()->resolve();
- $result = $this->didReceiveResult($result);
- $this->result = $result;
- }
- return $this->result;
- }
-
public function start() {
$this->getProxiedFuture()->start();
return $this;
diff --git a/src/future/ImmediateFuture.php b/src/future/ImmediateFuture.php
--- a/src/future/ImmediateFuture.php
+++ b/src/future/ImmediateFuture.php
@@ -7,7 +7,7 @@
final class ImmediateFuture extends Future {
public function __construct($result) {
- $this->result = $result;
+ $this->setResult($result);
}
public function isReady() {
diff --git a/src/future/exec/ExecFuture.php b/src/future/exec/ExecFuture.php
--- a/src/future/exec/ExecFuture.php
+++ b/src/future/exec/ExecFuture.php
@@ -381,22 +381,25 @@
* @task resolve
*/
public function resolveKill() {
- if (!$this->result) {
+ if (!$this->hasResult()) {
$signal = 9;
if ($this->proc) {
proc_terminate($this->proc, $signal);
}
- $this->result = array(
+ $result = array(
128 + $signal,
$this->stdout,
$this->stderr,
);
+
+ $this->setResult($result);
+
$this->closeProcess();
}
- return $this->result;
+ return $this->getResult();
}
@@ -764,11 +767,14 @@
}
}
- $this->result = array(
+ $result = array(
$err,
$this->stdout,
$this->stderr,
);
+
+ $this->setResult($result);
+
$this->closeProcess();
return true;
}
@@ -839,11 +845,18 @@
unset($this->windowsStderrTempFile);
if ($this->profilerCallID !== null) {
+ if ($this->hasResult()) {
+ $result = $this->getResult();
+ $err = idx($result, 0);
+ } else {
+ $err = null;
+ }
+
$profiler = PhutilServiceProfiler::getInstance();
$profiler->endServiceCall(
$this->profilerCallID,
array(
- 'err' => $this->result ? idx($this->result, 0) : null,
+ 'err' => $err,
));
$this->profilerCallID = null;
}
diff --git a/src/future/exec/PhutilExecPassthru.php b/src/future/exec/PhutilExecPassthru.php
--- a/src/future/exec/PhutilExecPassthru.php
+++ b/src/future/exec/PhutilExecPassthru.php
@@ -20,8 +20,6 @@
*/
final class PhutilExecPassthru extends PhutilExecutableFuture {
- private $passthruResult;
-
/* -( Executing Passthru Commands )---------------------------------------- */
@@ -105,15 +103,12 @@
// full control of the console. We're just implementing the interfaces to
// make it easier to share code with ExecFuture.
- if ($this->passthruResult === null) {
- $this->passthruResult = $this->execute();
+ if (!$this->hasResult()) {
+ $result = $this->execute();
+ $this->setResult($result);
}
return true;
}
- protected function getResult() {
- return $this->passthruResult;
- }
-
}
diff --git a/src/future/http/HTTPFuture.php b/src/future/http/HTTPFuture.php
--- a/src/future/http/HTTPFuture.php
+++ b/src/future/http/HTTPFuture.php
@@ -180,8 +180,9 @@
if (!$socket) {
$this->stateReady = true;
- $this->result = $this->buildErrorResult(
- HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED);
+ $this->setResult(
+ $this->buildErrorResult(
+ HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED));
return null;
}
@@ -209,16 +210,19 @@
$this->stateReady = true;
if ($timeout) {
- $this->result = $this->buildErrorResult(
- HTTPFutureTransportResponseStatus::ERROR_TIMEOUT);
+ $this->setResult(
+ $this->buildErrorResult(
+ HTTPFutureTransportResponseStatus::ERROR_TIMEOUT));
} else if (!$this->stateConnected) {
- $this->result = $this->buildErrorResult(
- HTTPFutureTransportResponseStatus::ERROR_CONNECTION_REFUSED);
+ $this->setResult(
+ $this->buildErrorResult(
+ HTTPFutureTransportResponseStatus::ERROR_CONNECTION_REFUSED));
} else if (!$this->stateWriteComplete) {
- $this->result = $this->buildErrorResult(
- HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED);
+ $this->setResult(
+ $this->buildErrorResult(
+ HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED));
} else {
- $this->result = $this->parseRawHTTPResponse($this->response);
+ $this->setResult($this->parseRawHTTPResponse($this->response));
}
$profiler = PhutilServiceProfiler::getInstance();
diff --git a/src/future/http/HTTPSFuture.php b/src/future/http/HTTPSFuture.php
--- a/src/future/http/HTTPSFuture.php
+++ b/src/future/http/HTTPSFuture.php
@@ -194,7 +194,7 @@
}
public function isReady() {
- if (isset($this->result)) {
+ if ($this->hasResult()) {
return true;
}
@@ -476,7 +476,7 @@
$body = null;
$headers = array();
- $this->result = array($status, $body, $headers);
+ $this->setResult(array($status, $body, $headers));
} else if ($this->parser) {
$streaming_parser = $this->parser;
try {
@@ -491,12 +491,12 @@
$result = array($ex, null, array());
}
- $this->result = $result;
+ $this->setResult($result);
} else {
// cURL returns headers of all redirects, we strip all but the final one.
$redirects = curl_getinfo($curl, CURLINFO_REDIRECT_COUNT);
$result = preg_replace('/^(.*\r\n\r\n){'.$redirects.'}/sU', '', $result);
- $this->result = $this->parseRawHTTPResponse($result);
+ $this->setResult($this->parseRawHTTPResponse($result));
}
curl_multi_remove_handle(self::$multi, $curl);
@@ -518,7 +518,7 @@
$sink = $this->getProgressSink();
if ($sink) {
- $status = head($this->result);
+ $status = head($this->getResult());
if ($status->isError()) {
$sink->didFailWork();
} else {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 29, 3:27 AM (3 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7708531
Default Alt Text
D21034.id.diff (8 KB)
Attached To
Mode
D21034: Make the "result" property on Future private
Attached
Detach File
Event Timeline
Log In to Comment