2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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_WAIT_HANDLE_H_
19 #define incl_HPHP_EXT_ASIO_WAIT_HANDLE_H_
21 #include "hphp/runtime/ext/extension.h"
22 #include "hphp/runtime/ext/asio/asio-blockable.h"
25 ///////////////////////////////////////////////////////////////////////////////
29 * A wait handle is an object that describes operation that is potentially
30 * asynchronous. A WaitHandle class is a base class of all such objects. There
31 * are multiple types of wait handles, this is their hierarchy:
33 * WaitHandle - abstract wait handle
34 * StaticWaitHandle - statically finished wait handle
35 * WaitableWaitHandle - wait handle that can be waited for
36 * ResumableWaitHandle - wait handle that can resume PHP execution
37 * AsyncFunctionWaitHandle - async function-based async execution
38 * AsyncGeneratorWaitHandle - async generator-based async execution
39 * AwaitAllWaitHandle - wait handle representing a collection of
40 * WHs, does not propagate results
41 * ConditionWaitHandle - wait handle implementing condition variable
42 * RescheduleWaitHandle - wait handle that reschedules execution
43 * SleepWaitHandle - wait handle that finishes after a timeout
44 * ExternalThreadEventWaitHandle - thread-powered asynchronous execution
47 * GenArrayWaitHandle - wait handle representing an array of WHs
48 * GenMapWaitHandle - wait handle representing an Map of WHs
49 * GenVectorWaitHandle - wait handle representing an Vector of WHs
51 * A wait handle can be either synchronously joined (waited for the operation
52 * to finish) or passed in various contexts as a dependency and waited for
53 * asynchronously (such as using await mechanism of async function or
54 * passed as an array member of GenArrayWaitHandle).
57 class c_AsyncFunctionWaitHandle
;
58 class c_AsyncGeneratorWaitHandle
;
59 class c_AwaitAllWaitHandle
;
60 class c_GenArrayWaitHandle
;
61 class c_GenMapWaitHandle
;
62 class c_GenVectorWaitHandle
;
63 class c_ConditionWaitHandle
;
64 class c_RescheduleWaitHandle
;
65 class c_SleepWaitHandle
;
66 class c_ExternalThreadEventWaitHandle
;
67 class c_WaitHandle
: public ExtObjectDataFlags
<ObjectData::IsWaitHandle
|
68 ObjectData::NoDestructor
> {
70 DECLARE_CLASS_NO_SWEEP(WaitHandle
)
72 enum class Kind
: uint8_t {
86 explicit c_WaitHandle(Class
* cls
= c_WaitHandle::classof(),
87 HeaderKind kind
= HeaderKind::Object
) noexcept
88 : ExtObjectDataFlags(cls
, kind
, NoInit
{}) {}
92 static void ti_setoniowaitentercallback(const Variant
& callback
);
93 static void ti_setoniowaitexitcallback(const Variant
& callback
);
94 static void ti_setonjoincallback(const Variant
& callback
);
95 Object
t_getwaithandle();
100 bool t_issucceeded();
106 static constexpr ptrdiff_t stateOff() {
107 return offsetof(c_WaitHandle
, m_kind_state
);
109 static constexpr ptrdiff_t resultOff() {
110 return offsetof(c_WaitHandle
, m_resultOrException
);
113 static c_WaitHandle
* fromCell(const Cell
* cell
) {
115 cell
->m_type
== KindOfObject
&&
116 cell
->m_data
.pobj
->getAttribute(ObjectData::IsWaitHandle
)
117 ) ? static_cast<c_WaitHandle
*>(cell
->m_data
.pobj
) : nullptr;
119 static c_WaitHandle
* fromCellAssert(const Cell
* cell
) {
120 assert(cell
->m_type
== KindOfObject
);
121 assert(cell
->m_data
.pobj
->getAttribute(ObjectData::IsWaitHandle
));
122 return static_cast<c_WaitHandle
*>(cell
->m_data
.pobj
);
124 bool isFinished() const { return getState() <= STATE_FAILED
; }
125 bool isSucceeded() const { return getState() == STATE_SUCCEEDED
; }
126 bool isFailed() const { return getState() == STATE_FAILED
; }
127 Cell
getResult() const {
128 assert(isSucceeded());
129 return m_resultOrException
;
131 ObjectData
* getException() const {
133 return m_resultOrException
.m_data
.pobj
;
136 Kind
getKind() const { return static_cast<Kind
>(m_kind_state
>> 4); }
137 uint8_t getState() const { return m_kind_state
& 0x0F; }
138 static uint8_t toKindState(Kind kind
, uint8_t state
) {
139 assert((uint8_t)kind
< 0x10 && state
< 0x10);
140 return ((uint8_t)kind
<< 4) | state
;
142 void setKindState(Kind kind
, uint8_t state
) {
143 m_kind_state
= toKindState(kind
, state
);
145 void setContextVectorIndex(uint32_t idx
) {
149 c_AsyncFunctionWaitHandle
* asAsyncFunction();
150 c_AsyncGeneratorWaitHandle
* asAsyncGenerator();
151 c_AwaitAllWaitHandle
* asAwaitAll();
152 c_GenArrayWaitHandle
* asGenArray();
153 c_GenMapWaitHandle
* asGenMap();
154 c_GenVectorWaitHandle
* asGenVector();
155 c_ConditionWaitHandle
* asCondition();
156 c_RescheduleWaitHandle
* asReschedule();
157 c_ResumableWaitHandle
* asResumable();
158 c_SleepWaitHandle
* asSleep();
159 c_ExternalThreadEventWaitHandle
* asExternalThreadEvent();
161 // The code in the TC will depend on the values of these constants.
163 static const int8_t STATE_SUCCEEDED
= 0;
164 static const int8_t STATE_FAILED
= 1;
166 private: // layout, ignoring ObjectData fields.
168 // [m_parentChain ][m_contextIdx][m_kind_state][ ][m_ctxVecIndex]
169 // [m_resultOrException.m_data][m_type] [m_aux]
170 static void checkLayout() {
171 constexpr auto data
= offsetof(c_WaitHandle
, m_resultOrException
);
172 constexpr auto type
= data
+ offsetof(TypedValue
, m_type
);
173 constexpr auto aux
= data
+ offsetof(TypedValue
, m_aux
);
174 static_assert(offsetof(c_WaitHandle
, m_parentChain
) == data
, "");
175 static_assert(offsetof(c_WaitHandle
, m_contextIdx
) == type
, "");
176 static_assert(offsetof(c_WaitHandle
, m_kind_state
) < aux
, "");
177 static_assert(offsetof(c_WaitHandle
, m_ctxVecIndex
) == aux
, "");
182 // STATE_SUCCEEDED || STATE_FAILED
183 Cell m_resultOrException
;
185 // !STATE_SUCCEEDED && !STATE_FAILED
187 // WaitableWaitHandle: !STATE_SUCCEEDED && !STATE_FAILED
188 AsioBlockableChain m_parentChain
;
190 // WaitableWaitHandle: !STATE_SUCCEEDED && !STATE_FAILED
191 context_idx_t m_contextIdx
;
193 // valid in any WaitHandle state. doesn't overlap Cell fields.
194 uint8_t m_kind_state
;
197 // ExternalThreadEventWaitHandle: STATE_WAITING
198 // SleepWaitHandle: STATE_WAITING
199 uint32_t m_ctxVecIndex
;
205 ///////////////////////////////////////////////////////////////////////////////
208 #endif // incl_HPHP_EXT_ASIO_WAIT_HANDLE_H_