Changeset View
Changeset View
Standalone View
Standalone View
src/future/Future.php
<?php | <?php | ||||
/** | /** | ||||
* A 'future' or 'promise' is an object which represents the result of some | * A 'future' or 'promise' is an object which represents the result of some | ||||
* pending computation. For a more complete overview of futures, see | * pending computation. For a more complete overview of futures, see | ||||
* @{article:Using Futures}. | * @{article:Using Futures}. | ||||
*/ | */ | ||||
abstract class Future extends Phobject { | abstract class Future extends Phobject { | ||||
private $hasResult = false; | private $hasResult = false; | ||||
private $hasStarted = false; | private $hasStarted = false; | ||||
private $hasEnded = false; | private $hasEnded = false; | ||||
private $result; | private $result; | ||||
private $exception; | private $exception; | ||||
private $futureKey; | private $futureKey; | ||||
private $serviceProfilerCallID; | |||||
/** | /** | ||||
* Is this future's process complete? Specifically, can this future be | * Is this future's process complete? Specifically, can this future be | ||||
* resolved without blocking? | * resolved without blocking? | ||||
* | * | ||||
* @return bool If true, the external process is complete and resolving this | * @return bool If true, the external process is complete and resolving this | ||||
* future will not block. | * future will not block. | ||||
*/ | */ | ||||
Show All 31 Lines | final public function startFuture() { | ||||
if ($this->hasStarted) { | if ($this->hasStarted) { | ||||
throw new Exception( | throw new Exception( | ||||
pht( | pht( | ||||
'Future has already started; futures can not start more '. | 'Future has already started; futures can not start more '. | ||||
'than once.')); | 'than once.')); | ||||
} | } | ||||
$this->hasStarted = true; | $this->hasStarted = true; | ||||
$this->startServiceProfiler(); | |||||
$this->isReady(); | $this->isReady(); | ||||
} | } | ||||
final public function updateFuture() { | final public function updateFuture() { | ||||
if ($this->hasException()) { | if ($this->hasException()) { | ||||
return; | return; | ||||
} | } | ||||
Show All 20 Lines | final public function endFuture() { | ||||
if ($this->hasEnded) { | if ($this->hasEnded) { | ||||
throw new Exception( | throw new Exception( | ||||
pht( | pht( | ||||
'Future has already ended; futures can not end more '. | 'Future has already ended; futures can not end more '. | ||||
'than once.')); | 'than once.')); | ||||
} | } | ||||
$this->hasEnded = true; | $this->hasEnded = true; | ||||
$this->endServiceProfiler(); | |||||
} | |||||
private function startServiceProfiler() { | |||||
// NOTE: This is a soft dependency so that we don't need to build the | |||||
// ServiceProfiler into the Phage agent. Normally, this class is always | |||||
// available. | |||||
if (!class_exists('PhutilServiceProfiler')) { | |||||
return; | |||||
} | } | ||||
$params = $this->getServiceProfilerStartParameters(); | |||||
$profiler = PhutilServiceProfiler::getInstance(); | |||||
$call_id = $profiler->beginServiceCall($params); | |||||
$this->serviceProfilerCallID = $call_id; | |||||
} | |||||
private function endServiceProfiler() { | |||||
$call_id = $this->serviceProfilerCallID; | |||||
if ($call_id === null) { | |||||
return; | |||||
} | |||||
$params = $this->getServiceProfilerResultParameters(); | |||||
$profiler = PhutilServiceProfiler::getInstance(); | |||||
$profiler->endServiceCall($call_id, $params); | |||||
} | |||||
protected function getServiceProfilerStartParameters() { | |||||
return array(); | |||||
} | |||||
protected function getServiceProfilerResultParameters() { | |||||
return array(); | |||||
} | |||||
/** | /** | ||||
* Retrieve a list of sockets which we can wait to become readable while | * 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 | * a future is resolving. If your future has sockets which can be | ||||
* `select()`ed, return them here (or in @{method:getWriteSockets}) to make | * `select()`ed, return them here (or in @{method:getWriteSockets}) to make | ||||
* the resolve loop do a `select()`. If you do not return sockets in either | * the resolve loop do a `select()`. If you do not return sockets in either | ||||
* case, you'll get a busy wait. | * case, you'll get a busy wait. | ||||
* | * | ||||
* @return list A list of sockets which we expect to become readable. | * @return list A list of sockets which we expect to become readable. | ||||
▲ Show 20 Lines • Show All 103 Lines • Show Last 20 Lines |