PluginProbe
Gmail SMTP / trunk
Gmail SMTP vtrunk
1.2.3.21 1.2.3.20 trunk 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.9 1.2.0 1.2.3.14 1.2.3.15 1.2.3.16 1.2.3.18 1.2.3.5
gmail-smtp / google-api-php-client / vendor / guzzlehttp / promises / src / Coroutine.php

Coroutine.php in Gmail SMTP trunk, at google-api-php-client/vendor/guzzlehttp/promises/src/Coroutine.php

166 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace GuzzleHttp\Promise;
6
7 use Generator;
8 use Throwable;
9
10 /**
11 * Creates a promise that is resolved using a generator that yields values or
12 * promises (somewhat similar to C#'s async keyword).
13 *
14 * When called, the Coroutine::of method will start an instance of the generator
15 * and returns a promise that is fulfilled with its final yielded value.
16 *
17 * Control is returned back to the generator when the yielded promise settles.
18 * This can lead to less verbose code when doing lots of sequential async calls
19 * with minimal processing in between.
20 *
21 * use GuzzleHttp\Promise;
22 *
23 * function createPromise($value) {
24 * return new Promise\FulfilledPromise($value);
25 * }
26 *
27 * $promise = Promise\Coroutine::of(function () {
28 * $value = (yield createPromise('a'));
29 * try {
30 * $value = (yield createPromise($value . 'b'));
31 * } catch (\Throwable $e) {
32 * // The promise was rejected.
33 * }
34 * yield $value . 'c';
35 * });
36 *
37 * // Outputs "abc"
38 * $promise->then(function ($v) { echo $v; });
39 *
40 * @param callable $generatorFn Generator function to wrap into a promise.
41 *
42 * @return Promise
43 *
44 * @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
45 */
46 final class Coroutine implements PromiseInterface
47 {
48 /**
49 * @var PromiseInterface|null
50 */
51 private $currentPromise;
52
53 /**
54 * @var Generator
55 */
56 private $generator;
57
58 /**
59 * @var Promise
60 */
61 private $result;
62
63 public function __construct(callable $generatorFn)
64 {
65 $this->generator = $generatorFn();
66 $this->result = new Promise(function (): void {
67 while (isset($this->currentPromise)) {
68 $this->currentPromise->wait();
69 }
70 });
71 try {
72 $this->nextCoroutine($this->generator->current());
73 } catch (Throwable $throwable) {
74 $this->result->reject($throwable);
75 }
76 }
77
78 /**
79 * Create a new coroutine.
80 */
81 public static function of(callable $generatorFn): self
82 {
83 return new self($generatorFn);
84 }
85
86 public function then(
87 ?callable $onFulfilled = null,
88 ?callable $onRejected = null
89 ): PromiseInterface {
90 return $this->result->then($onFulfilled, $onRejected);
91 }
92
93 public function otherwise(callable $onRejected): PromiseInterface
94 {
95 return $this->result->otherwise($onRejected);
96 }
97
98 public function wait(bool $unwrap = true)
99 {
100 return $this->result->wait($unwrap);
101 }
102
103 public function getState(): string
104 {
105 return $this->result->getState();
106 }
107
108 public function resolve($value): void
109 {
110 $this->result->resolve($value);
111 }
112
113 public function reject($reason): void
114 {
115 $this->result->reject($reason);
116 }
117
118 public function cancel(): void
119 {
120 if (isset($this->currentPromise)) {
121 $this->currentPromise->cancel();
122 }
123
124 $this->result->cancel();
125 }
126
127 private function nextCoroutine($yielded): void
128 {
129 $this->currentPromise = Create::promiseFor($yielded)
130 ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
131 }
132
133 /**
134 * @internal
135 */
136 public function _handleSuccess($value): void
137 {
138 unset($this->currentPromise);
139 try {
140 $next = $this->generator->send($value);
141 if ($this->generator->valid()) {
142 $this->nextCoroutine($next);
143 } else {
144 $this->result->resolve($value);
145 }
146 } catch (Throwable $throwable) {
147 $this->result->reject($throwable);
148 }
149 }
150
151 /**
152 * @internal
153 */
154 public function _handleFailure($reason): void
155 {
156 unset($this->currentPromise);
157 try {
158 $nextYield = $this->generator->throw(Create::exceptionFor($reason));
159 // The throw was caught, so keep iterating on the coroutine
160 $this->nextCoroutine($nextYield);
161 } catch (Throwable $throwable) {
162 $this->result->reject($throwable);
163 }
164 }
165 }
166