2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #ifndef incl_HPHP_EXT_ASIO_H_
19 #define incl_HPHP_EXT_ASIO_H_
21 #include <runtime/base/base_includes.h>
22 #include <runtime/ext/asio/asio_session.h>
25 ///////////////////////////////////////////////////////////////////////////////
27 int f_asio_get_current_context_idx();
28 Object
f_asio_get_running_in_context(int ctx_idx
);
29 Object
f_asio_get_running();
30 void f_asio_set_on_failed_callback(CVarRef on_failed_cb
);
31 void f_asio_set_on_started_callback(CVarRef on_started_cb
);
33 ///////////////////////////////////////////////////////////////////////////////
37 * A wait handle is an object that describes operation that is potentially
38 * asynchronous. A WaitHandle class is a base class of all such objects. There
39 * are multiple types of wait handles, this is their hierarchy:
41 * WaitHandle - abstract wait handle
42 * StaticWaitHandle - statically finished wait handle
43 * StaticResultWaitHandle - statically succeeded wait handle with result
44 * StaticExceptionWaitHandle - statically failed wait handle with exception
45 * WaitableWaitHandle - wait handle that can be waited for
46 * BlockableWaitHandle - wait handle that can be blocked by other WH
47 * ContinuationWaitHandle - Continuation-powered asynchronous execution
48 * GenArrayWaitHandle - wait handle representing an array of WHs
49 * SetResultToRefWaitHandle - wait handle that sets result to reference
50 * RescheduleWaitHandle - wait handle that reschedules execution
52 * A wait handle can be either synchronously joined (waited for the operation
53 * to finish) or passed in various contexts as a dependency and waited for
54 * asynchronously (such as using yield mechanism of ContinuationWaitHandle or
55 * passed as an array member of GenArrayWaitHandle).
57 FORWARD_DECLARE_CLASS_BUILTIN(WaitHandle
);
58 class c_WaitHandle
: public ExtObjectData
{
60 DECLARE_CLASS(WaitHandle
, WaitHandle
, ObjectData
)
63 public: c_WaitHandle(VM::Class
* cls
= c_WaitHandle::s_cls
);
64 public: ~c_WaitHandle();
65 public: void t___construct();
66 public: Object
t_getwaithandle();
67 public: void t_import();
68 public: Variant
t_join();
69 public: bool t_isfinished();
70 public: bool t_issucceeded();
71 public: bool t_isfailed();
72 public: int64_t t_getid();
73 public: String
t_getname();
74 public: Object
t_getexceptioniffailed();
78 static c_WaitHandle
* fromTypedValue(TypedValue
* tv
) {
80 tv
->m_type
== KindOfObject
&&
81 tv
->m_data
.pobj
->instanceof(s_cls
)
82 ) ? static_cast<c_WaitHandle
*>(tv
->m_data
.pobj
) : nullptr;
84 bool isFinished() { return getState() <= STATE_FAILED
; }
85 bool isSucceeded() { return getState() == STATE_SUCCEEDED
; }
86 bool isFailed() { return getState() == STATE_FAILED
; }
87 TypedValue
* getResult() { assert(isSucceeded()); return &m_resultOrException
; }
88 ObjectData
* getException() { assert(isFailed()); return m_resultOrException
.m_data
.pobj
; }
89 virtual String
getName() = 0;
92 uint8_t getState() { return o_subclassData
.u8
[0]; }
93 void setState(uint8_t state
) { o_subclassData
.u8
[0] = state
; }
95 static const int8_t STATE_SUCCEEDED
= 0;
96 static const int8_t STATE_FAILED
= 1;
98 TypedValue m_resultOrException
;
101 ///////////////////////////////////////////////////////////////////////////////
102 // class StaticWaitHandle
105 * A static wait handle is a wait handle that is statically finished. The result
106 * of the operation is always available and waiting for the wait handle finishes
109 FORWARD_DECLARE_CLASS_BUILTIN(StaticWaitHandle
);
110 class c_StaticWaitHandle
: public c_WaitHandle
{
112 DECLARE_CLASS(StaticWaitHandle
, StaticWaitHandle
, WaitHandle
)
115 public: c_StaticWaitHandle(VM::Class
* cls
= c_StaticWaitHandle::s_cls
);
116 public: ~c_StaticWaitHandle();
117 public: void t___construct();
121 ///////////////////////////////////////////////////////////////////////////////
122 // class StaticResultWaitHandle
125 * A wait handle that is statically succeeded with a result.
127 FORWARD_DECLARE_CLASS_BUILTIN(StaticResultWaitHandle
);
128 class c_StaticResultWaitHandle
: public c_StaticWaitHandle
{
130 DECLARE_CLASS(StaticResultWaitHandle
, StaticResultWaitHandle
, StaticWaitHandle
)
133 public: c_StaticResultWaitHandle(VM::Class
* cls
= c_StaticResultWaitHandle::s_cls
);
134 public: ~c_StaticResultWaitHandle();
135 public: void t___construct();
136 public: static Object
ti_create(const char* cls
, CVarRef result
);
137 public: static Object
t_create(CVarRef result
) {
138 return ti_create("staticresultwaithandle", result
);
143 static p_StaticResultWaitHandle
Create(const TypedValue
* result
);
147 ///////////////////////////////////////////////////////////////////////////////
148 // class StaticExceptionWaitHandle
151 * A wait handle that is statically failed with an exception.
153 FORWARD_DECLARE_CLASS_BUILTIN(StaticExceptionWaitHandle
);
154 class c_StaticExceptionWaitHandle
: public c_StaticWaitHandle
{
156 DECLARE_CLASS(StaticExceptionWaitHandle
, StaticExceptionWaitHandle
, StaticWaitHandle
)
159 public: c_StaticExceptionWaitHandle(VM::Class
* cls
= c_StaticExceptionWaitHandle::s_cls
);
160 public: ~c_StaticExceptionWaitHandle();
161 public: void t___construct();
162 public: static Object
ti_create(const char* cls
, CObjRef exception
);
163 public: static Object
t_create(CObjRef exception
) {
164 return ti_create("staticexceptionwaithandle", exception
);
169 static p_StaticExceptionWaitHandle
Create(ObjectData
* exception
);
173 ///////////////////////////////////////////////////////////////////////////////
174 // class WaitableWaitHandle
177 * A waitable wait handle is a wait handle that can be waited for by a blockable
178 * wait handle if a result is not yet available. Once the wait handle finishes,
179 * all blocked wait handles are notified.
182 FORWARD_DECLARE_CLASS_BUILTIN(BlockableWaitHandle
);
183 FORWARD_DECLARE_CLASS_BUILTIN(WaitableWaitHandle
);
184 class c_WaitableWaitHandle
: public c_WaitHandle
{
186 DECLARE_CLASS(WaitableWaitHandle
, WaitableWaitHandle
, WaitHandle
)
189 public: c_WaitableWaitHandle(VM::Class
* cls
= c_WaitableWaitHandle::s_cls
);
190 public: ~c_WaitableWaitHandle();
191 public: void t___construct();
192 public: int t_getcontextidx();
193 public: Object
t_getcreator();
194 public: Array
t_getparents();
198 AsioContext
* getContext() { assert(isInContext()); return AsioSession::Get()->getContext(getContextIdx()); }
200 c_BlockableWaitHandle
* addParent(c_BlockableWaitHandle
* parent
);
202 virtual void enterContext(context_idx_t ctx_idx
) = 0;
206 void setResult(const TypedValue
* result
);
207 void setException(ObjectData
* exception
);
209 context_idx_t
getContextIdx() { return o_subclassData
.u8
[1]; }
210 void setContextIdx(context_idx_t ctx_idx
) { o_subclassData
.u8
[1] = ctx_idx
; }
212 bool isInContext() { return getContextIdx(); }
214 c_BlockableWaitHandle
* getFirstParent() { return m_firstParent
; }
216 virtual c_WaitableWaitHandle
* getChild();
217 bool hasCycle(c_WaitableWaitHandle
* start
);
219 static const int8_t STATE_NEW
= 2;
222 c_ContinuationWaitHandle
* m_creator
;
223 c_BlockableWaitHandle
* m_firstParent
;
226 ///////////////////////////////////////////////////////////////////////////////
227 // class BlockableWaitHandle
230 * A blockable wait handle is a wait handle that can be blocked by a waitable
231 * wait handle it is waiting for. Once a wait handle blocking this wait handle
232 * is finished, a notification is received and the operation can be resumed.
234 FORWARD_DECLARE_CLASS_BUILTIN(BlockableWaitHandle
);
235 class c_BlockableWaitHandle
: public c_WaitableWaitHandle
{
237 DECLARE_CLASS(BlockableWaitHandle
, BlockableWaitHandle
, WaitableWaitHandle
)
240 public: c_BlockableWaitHandle(VM::Class
* cls
= c_BlockableWaitHandle::s_cls
);
241 public: ~c_BlockableWaitHandle();
242 public: void t___construct();
246 c_BlockableWaitHandle
* getNextParent();
247 c_BlockableWaitHandle
* unblock();
249 void exitContextBlocked(context_idx_t ctx_idx
);
252 void blockOn(c_WaitableWaitHandle
* child
);
253 virtual void onUnblocked() = 0;
254 c_WaitableWaitHandle
* getChild() = 0;
256 static const int8_t STATE_BLOCKED
= 3;
259 void reportCycle(c_WaitableWaitHandle
* start
);
261 c_BlockableWaitHandle
* m_nextParent
;
264 ///////////////////////////////////////////////////////////////////////////////
265 // class ContinuationWaitHandle
268 * A continuation wait handle represents a basic unit of asynchronous execution
269 * powered by continuation object. An asynchronous program can be written using
270 * continuations; a dependency on another wait handle is set up by yielding such
271 * wait handle, giving control of the execution back to the asio framework.
273 FORWARD_DECLARE_CLASS_BUILTIN(Continuation
);
274 FORWARD_DECLARE_CLASS_BUILTIN(ContinuationWaitHandle
);
275 class c_ContinuationWaitHandle
: public c_BlockableWaitHandle
{
277 DECLARE_CLASS(ContinuationWaitHandle
, ContinuationWaitHandle
, BlockableWaitHandle
)
280 public: c_ContinuationWaitHandle(VM::Class
* cls
= c_ContinuationWaitHandle::s_cls
);
281 public: ~c_ContinuationWaitHandle();
282 public: void t___construct();
283 public: static Object
ti_start(const char* cls
, CObjRef continuation
);
284 public: static Object
t_start(CObjRef continuation
) {
285 return ti_start("continuationwaithandle", continuation
);
287 public: Object
t_getprivdata();
288 public: void t_setprivdata(CObjRef data
);
293 uint16_t getDepth() { return m_depth
; }
295 void enterContext(context_idx_t ctx_idx
);
296 void exitContext(context_idx_t ctx_idx
);
300 c_WaitableWaitHandle
* getChild();
303 void start(c_Continuation
* continuation
, uint16_t depth
);
304 void markAsSucceeded(const TypedValue
* result
);
305 void markAsFailed(CObjRef exception
);
307 p_Continuation m_continuation
;
308 p_WaitHandle m_child
;
312 static const int8_t STATE_SCHEDULED
= 4;
313 static const int8_t STATE_RUNNING
= 5;
316 ///////////////////////////////////////////////////////////////////////////////
317 // class GenArrayWaitHandle
320 * A wait handle that waits for an array of wait handles. The wait handle
321 * finishes once all wait handles in the array are finished. The result value
322 * preserves structure (order and keys) of the original array. If one of the
323 * wait handles failed, the exception is propagated by failure.
325 FORWARD_DECLARE_CLASS_BUILTIN(GenArrayWaitHandle
);
326 class c_GenArrayWaitHandle
: public c_BlockableWaitHandle
{
328 DECLARE_CLASS(GenArrayWaitHandle
, GenArrayWaitHandle
, BlockableWaitHandle
)
331 public: c_GenArrayWaitHandle(VM::Class
* cls
= c_GenArrayWaitHandle::s_cls
);
332 public: ~c_GenArrayWaitHandle();
333 public: void t___construct();
334 public: static Object
ti_create(const char* cls
, CArrRef dependencies
);
335 public: static Object
t_create(CArrRef dependencies
) {
336 return ti_create("genarraywaithandle", dependencies
);
342 void enterContext(context_idx_t ctx_idx
);
346 c_WaitableWaitHandle
* getChild();
349 void initialize(CObjRef exception
, CArrRef deps
, ssize_t iter_pos
, c_WaitableWaitHandle
* child
);
356 ///////////////////////////////////////////////////////////////////////////////
357 // class SetResultToRefWaitHandle
360 * A wait handle that waits for a given dependency and sets its result to
361 * a given reference once completed.
363 FORWARD_DECLARE_CLASS_BUILTIN(SetResultToRefWaitHandle
);
364 class c_SetResultToRefWaitHandle
: public c_BlockableWaitHandle
{
366 DECLARE_CLASS(SetResultToRefWaitHandle
, SetResultToRefWaitHandle
, BlockableWaitHandle
)
369 public: c_SetResultToRefWaitHandle(VM::Class
* cls
= c_SetResultToRefWaitHandle::s_cls
);
370 public: ~c_SetResultToRefWaitHandle();
371 public: void t___construct();
372 public: static Object
ti_create(const char* cls
, CObjRef wait_handle
, VRefParam ref
);
373 public: static Object
t_create(CObjRef wait_handle
, VRefParam ref
) {
374 return ti_create("setresulttorefwaithandle", wait_handle
, ref
);
380 void enterContext(context_idx_t ctx_idx
);
384 c_WaitableWaitHandle
* getChild();
387 void initialize(c_WaitableWaitHandle
* wait_handle
, RefData
* ref
);
388 void markAsSucceeded(const TypedValue
* result
);
389 void markAsFailed(CObjRef exception
);
391 p_WaitableWaitHandle m_child
;
395 ///////////////////////////////////////////////////////////////////////////////
396 // class RescheduleWaitHandle
398 extern const int q_RescheduleWaitHandle$$QUEUE_DEFAULT
;
399 extern const int q_RescheduleWaitHandle$$QUEUE_NO_PENDING_IO
;
402 * A wait handle that is enqueued into a given priority queue and once desired
403 * execution priority is eligible for execution, it succeeds with a null result.
405 * RescheduleWaitHandle is guaranteed to never finish immediately.
407 FORWARD_DECLARE_CLASS_BUILTIN(RescheduleWaitHandle
);
408 class c_RescheduleWaitHandle
: public c_WaitableWaitHandle
{
410 DECLARE_CLASS(RescheduleWaitHandle
, RescheduleWaitHandle
, WaitableWaitHandle
)
413 public: c_RescheduleWaitHandle(VM::Class
* cls
= c_RescheduleWaitHandle::s_cls
);
414 public: ~c_RescheduleWaitHandle();
415 public: void t___construct();
416 public: static Object
ti_create(const char* cls
, int queue
, int priority
);
417 public: static Object
t_create(int queue
, int priority
) {
418 return ti_create("reschedulewaithandle", queue
, priority
);
424 void enterContext(context_idx_t ctx_idx
);
425 void exitContext(context_idx_t ctx_idx
);
428 void initialize(uint32_t queue
, uint32_t priority
);
433 static const int8_t STATE_SCHEDULED
= 3;
436 ///////////////////////////////////////////////////////////////////////////////
437 // class ExternalThreadEventWaitHandle
440 * A wait handle that synchronizes against C++ operation in external thread.
442 * See asio_external_thread_event.h for more details.
444 class AsioExternalThreadEvent
;
445 FORWARD_DECLARE_CLASS_BUILTIN(ExternalThreadEventWaitHandle
);
446 class c_ExternalThreadEventWaitHandle
: public c_WaitableWaitHandle
, public Sweepable
{
448 DECLARE_CLASS(ExternalThreadEventWaitHandle
, ExternalThreadEventWaitHandle
, WaitableWaitHandle
)
451 public: c_ExternalThreadEventWaitHandle(VM::Class
* cls
= c_ExternalThreadEventWaitHandle::s_cls
);
452 public: ~c_ExternalThreadEventWaitHandle();
453 public: void t___construct();
456 static c_ExternalThreadEventWaitHandle
* Create(AsioExternalThreadEvent
* event
);
458 c_ExternalThreadEventWaitHandle
* getNextToProcess() { assert(getState() == STATE_WAITING
); return m_nextToProcess
; }
459 void setNextToProcess(c_ExternalThreadEventWaitHandle
* next
) { assert(getState() == STATE_WAITING
); m_nextToProcess
= next
; }
460 void setIndex(uint32_t ete_idx
) { assert(getState() == STATE_WAITING
); m_index
= ete_idx
; }
462 void abandon(bool sweeping
);
465 void enterContext(context_idx_t ctx_idx
);
466 void exitContext(context_idx_t ctx_idx
);
469 void initialize(AsioExternalThreadEvent
* event
);
471 c_ExternalThreadEventWaitHandle
* m_nextToProcess
;
472 AsioExternalThreadEvent
* m_event
;
475 static const uint8_t STATE_WAITING
= 3;
478 ///////////////////////////////////////////////////////////////////////////////
481 #endif // incl_HPHP_EXT_ASIO_H_