src/async/Condition.php (39 lines of code) (raw):

<?hh /* * Copyright (c) 2004-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the hphp/hsl/ subdirectory of this source tree. * */ namespace HH\Lib\Async; /** * A wrapper around ConditionWaitHandle that allows notification events * to occur before the condition is awaited. */ class Condition<T> { private ?Awaitable<T> $condition = null; /** * Notify the condition variable of success and set the result. */ final public function succeed(T $result): void { if ($this->condition === null) { $this->condition = async { return $result; }; } else { invariant( $this->condition is ConditionWaitHandle<_>, 'Unable to notify AsyncCondition twice', ); /* HH_FIXME[4110]: Type error revealed by type-safe instanceof feature. See https://fburl.com/instanceof */ $this->condition->succeed($result); } } /** * Notify the condition variable of failure and set the exception. */ final public function fail(\Exception $exception): void { if ($this->condition === null) { $this->condition = async { throw $exception; }; } else { invariant( $this->condition is ConditionWaitHandle<_>, 'Unable to notify AsyncCondition twice', ); $this->condition->fail($exception); } } /** * Asynchronously wait for the condition variable to be notified and * return the result or throw the exception received via notification. * * The caller must provide an Awaitable $notifiers (which must be a * WaitHandle) that must not finish before the notification is received. * This means $notifiers must represent work that is guaranteed to * eventually trigger the notification. As long as the notification is * issued only once, asynchronous execution unrelated to $notifiers is * allowed to trigger the notification. */ final public async function waitForNotificationAsync( Awaitable<void> $notifiers, ): Awaitable<T> { if ($this->condition === null) { $this->condition = ConditionWaitHandle::create($notifiers); } return await $this->condition; } }