Add support for external thread events
[hiphop-php.git] / hphp / runtime / ext / ext_asio.h
blob4084115ad0e0bed339bd022da33514c4b8477488
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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>
24 namespace HPHP {
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 ///////////////////////////////////////////////////////////////////////////////
34 // class WaitHandle
36 /**
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 {
59 public:
60 DECLARE_CLASS(WaitHandle, WaitHandle, ObjectData)
62 // need to implement
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();
77 public:
78 static c_WaitHandle* fromTypedValue(TypedValue* tv) {
79 return (
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;
91 protected:
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
107 * immediately.
109 FORWARD_DECLARE_CLASS_BUILTIN(StaticWaitHandle);
110 class c_StaticWaitHandle : public c_WaitHandle {
111 public:
112 DECLARE_CLASS(StaticWaitHandle, StaticWaitHandle, WaitHandle)
114 // need to implement
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 {
129 public:
130 DECLARE_CLASS(StaticResultWaitHandle, StaticResultWaitHandle, StaticWaitHandle)
132 // need to implement
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);
142 public:
143 static p_StaticResultWaitHandle Create(const TypedValue* result);
144 String getName();
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 {
155 public:
156 DECLARE_CLASS(StaticExceptionWaitHandle, StaticExceptionWaitHandle, StaticWaitHandle)
158 // need to implement
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);
168 public:
169 static p_StaticExceptionWaitHandle Create(ObjectData* exception);
170 String getName();
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.
181 class AsioContext;
182 FORWARD_DECLARE_CLASS_BUILTIN(BlockableWaitHandle);
183 FORWARD_DECLARE_CLASS_BUILTIN(WaitableWaitHandle);
184 class c_WaitableWaitHandle : public c_WaitHandle {
185 public:
186 DECLARE_CLASS(WaitableWaitHandle, WaitableWaitHandle, WaitHandle)
188 // need to implement
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();
197 public:
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;
203 void join();
205 protected:
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;
221 private:
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 {
236 public:
237 DECLARE_CLASS(BlockableWaitHandle, BlockableWaitHandle, WaitableWaitHandle)
239 // need to implement
240 public: c_BlockableWaitHandle(VM::Class* cls = c_BlockableWaitHandle::s_cls);
241 public: ~c_BlockableWaitHandle();
242 public: void t___construct();
245 public:
246 c_BlockableWaitHandle* getNextParent();
247 c_BlockableWaitHandle* unblock();
249 void exitContextBlocked(context_idx_t ctx_idx);
251 protected:
252 void blockOn(c_WaitableWaitHandle* child);
253 virtual void onUnblocked() = 0;
254 c_WaitableWaitHandle* getChild() = 0;
256 static const int8_t STATE_BLOCKED = 3;
258 private:
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 {
276 public:
277 DECLARE_CLASS(ContinuationWaitHandle, ContinuationWaitHandle, BlockableWaitHandle)
279 // need to implement
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);
291 public:
292 void run();
293 uint16_t getDepth() { return m_depth; }
294 String getName();
295 void enterContext(context_idx_t ctx_idx);
296 void exitContext(context_idx_t ctx_idx);
298 protected:
299 void onUnblocked();
300 c_WaitableWaitHandle* getChild();
302 private:
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;
309 Object m_privData;
310 uint16_t m_depth;
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 {
327 public:
328 DECLARE_CLASS(GenArrayWaitHandle, GenArrayWaitHandle, BlockableWaitHandle)
330 // need to implement
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);
340 public:
341 String getName();
342 void enterContext(context_idx_t ctx_idx);
344 protected:
345 void onUnblocked();
346 c_WaitableWaitHandle* getChild();
348 private:
349 void initialize(CObjRef exception, CArrRef deps, ssize_t iter_pos, c_WaitableWaitHandle* child);
351 Object m_exception;
352 Array m_deps;
353 ssize_t m_iterPos;
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 {
365 public:
366 DECLARE_CLASS(SetResultToRefWaitHandle, SetResultToRefWaitHandle, BlockableWaitHandle)
368 // need to implement
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);
378 public:
379 String getName();
380 void enterContext(context_idx_t ctx_idx);
382 protected:
383 void onUnblocked();
384 c_WaitableWaitHandle* getChild();
386 private:
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;
392 RefData* m_ref;
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 {
409 public:
410 DECLARE_CLASS(RescheduleWaitHandle, RescheduleWaitHandle, WaitableWaitHandle)
412 // need to implement
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);
421 public:
422 void run();
423 String getName();
424 void enterContext(context_idx_t ctx_idx);
425 void exitContext(context_idx_t ctx_idx);
427 private:
428 void initialize(uint32_t queue, uint32_t priority);
430 uint32_t m_queue;
431 uint32_t m_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 {
447 public:
448 DECLARE_CLASS(ExternalThreadEventWaitHandle, ExternalThreadEventWaitHandle, WaitableWaitHandle)
450 // need to implement
451 public: c_ExternalThreadEventWaitHandle(VM::Class* cls = c_ExternalThreadEventWaitHandle::s_cls);
452 public: ~c_ExternalThreadEventWaitHandle();
453 public: void t___construct();
455 public:
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);
463 void process();
464 String getName();
465 void enterContext(context_idx_t ctx_idx);
466 void exitContext(context_idx_t ctx_idx);
468 private:
469 void initialize(AsioExternalThreadEvent* event);
471 c_ExternalThreadEventWaitHandle* m_nextToProcess;
472 AsioExternalThreadEvent* m_event;
473 uint32_t m_index;
475 static const uint8_t STATE_WAITING = 3;
478 ///////////////////////////////////////////////////////////////////////////////
481 #endif // incl_HPHP_EXT_ASIO_H_