-
Notifications
You must be signed in to change notification settings - Fork 38
/
KernelApi.php
224 lines (202 loc) · 6.26 KB
/
KernelApi.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<?php
namespace Recoil\Kernel\Api;
use Exception;
use Recoil\Kernel\Strand\StrandInterface;
/**
* The default kernel API implementation.
*/
class KernelApi implements KernelApiInterface
{
/**
* Get the strand the coroutine is executing on.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function strand(StrandInterface $strand)
{
$strand->resumeWithValue($strand);
}
/**
* Get the coroutine kernel that the current strand is executing on.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function kernel(StrandInterface $strand)
{
$strand->resumeWithValue($strand->kernel());
}
/**
* Get the React event-loop that the coroutine kernel is executing on.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function eventLoop(StrandInterface $strand)
{
$strand->resumeWithValue($strand->kernel()->eventLoop());
}
/**
* Return a value to the calling coroutine.
*
* @param StrandInterface $strand The currently executing strand.
* @param mixed $value The value to send to the calling coroutine.
*/
public function return_(StrandInterface $strand, $value = null)
{
$strand->returnValue($value);
}
/**
* Throw an exception to the calling coroutine.
*
* @param StrandInterface $strand The currently executing strand.
* @param Exception $exception The error to send to the calling coroutine.
*/
public function throw_(StrandInterface $strand, Exception $exception)
{
$strand->throwException($exception);
}
/**
* Register a callback to be invoked when the current coroutine is popped
* from the call stack.
*
* The callback is guaranteed to be called even if a reference to the
* coroutine is held elsewhere (unlike a PHP finally block in a generator).
*
* @param StrandInterface $strand The currently executing strand.
* @param callable $callback The callback to invoke.
*/
public function finally_(StrandInterface $strand, callable $callback)
{
$strand->current()->once('finalize', $callback);
$strand->resumeWithValue(null);
}
/**
* Terminate execution of the strand.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function terminate(StrandInterface $strand)
{
$strand->terminate();
}
/**
* Suspend execution for a specified period of time.
*
* @param StrandInterface $strand The currently executing strand.
* @param number $timeout The number of seconds to wait before resuming.
*/
public function sleep(StrandInterface $strand, $timeout)
{
$strand->call(
new Sleep($timeout)
);
}
/**
* Suspend execution of the strand.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function suspend(StrandInterface $strand, callable $callback)
{
$strand->suspend();
$callback($strand);
}
/**
* Execute a coroutine with a time limit.
*
* If the coroutine does not complete within the specified time it is
* cancelled.
*
* @param StrandInterface $strand The currently executing strand.
* @param number $timeout The number of seconds to wait before cancelling.
* @param mixed $coroutine The coroutine to execute.
*/
public function timeout(StrandInterface $strand, $timeout, $coroutine)
{
$strand->call(
new Timeout($timeout, $coroutine)
);
}
/**
* Execute the given coroutines concurrently.
*
* Execution of the current strand is suspended until all of the coroutines
* are completed. If any of the coroutines fails, the remaining coroutines
* are terminated.
*
* @param StrandInterface $strand The currently executing strand.
* @param array $coroutines The coroutines to execute.
*/
public function all(StrandInterface $strand, array $coroutines)
{
$strand->call(
new WaitAll($coroutines)
);
}
/**
* Suspend the strand until the next tick.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function cooperate(StrandInterface $strand)
{
$strand->suspend();
$strand
->kernel()
->eventLoop()
->nextTick(
function () use ($strand) {
$strand->resumeWithValue(null);
}
);
}
/**
* Resume the strand immediately.
*
* @param StrandInterface $strand The currently executing strand.
*/
public function noop(StrandInterface $strand)
{
$strand->resumeWithValue(null);
}
/**
* Execute a coroutine on its own strand.
*
* @param StrandInterface $strand The currently executing strand.
* @param mixed $coroutine The coroutine to execute.
*/
public function execute(StrandInterface $strand, $coroutine)
{
$substrand = $strand
->kernel()
->execute($coroutine);
$strand->resumeWithValue($substrand);
}
/**
* Stop the coroutine kernel / event-loop.
*
* The React event-loop can optionally be stopped when all strands have been
* terminated.
*
* @param StrandInterface $strand The currently executing strand.
* @param boolean $stopEventLoop Indicates whether or not the React event-loop should also be stopped.
*/
public function stop(StrandInterface $strand, $stopEventLoop = true)
{
$strand->terminate();
$strand
->kernel()
->stop($stopEventLoop);
}
/**
* Wait for one or more of the given strands to exit.
*
* @param StrandInterface $strand The currently executing strand.
* @param array<StrandInterface> $strands The strands to wait for.
*/
public function select(StrandInterface $strand, array $strands)
{
$strand->call(
new Select($strands)
);
}
}