Optimize newInstanceRaw by fully initializing ObjectData attributes
[hiphop-php.git] / hphp / runtime / ext / asio / ext_wait-handle.h
blobb90b6a326d3162a16febdcf9f2d9034e53d3b83a
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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"
24 namespace HPHP {
25 ///////////////////////////////////////////////////////////////////////////////
26 // class WaitHandle
28 void HHVM_STATIC_METHOD(WaitHandle, setOnIoWaitEnterCallback,
29 const Variant& callback);
30 void HHVM_STATIC_METHOD(WaitHandle, setOnIoWaitExitCallback,
31 const Variant& callback);
32 void HHVM_STATIC_METHOD(WaitHandle, setOnJoinCallback,
33 const Variant& callback);
34 bool HHVM_METHOD(WaitHandle, isFinished);
35 bool HHVM_METHOD(WaitHandle, isSucceeded);
36 bool HHVM_METHOD(WaitHandle, isFailed);
37 String HHVM_METHOD(WaitHandle, getName);
39 /**
40 * A wait handle is an object that describes operation that is potentially
41 * asynchronous. A WaitHandle class is a base class of all such objects. There
42 * are multiple types of wait handles, this is their hierarchy:
44 * WaitHandle - abstract wait handle
45 * StaticWaitHandle - statically finished wait handle
46 * WaitableWaitHandle - wait handle that can be waited for
47 * ResumableWaitHandle - wait handle that can resume PHP execution
48 * AsyncFunctionWaitHandle - async function-based async execution
49 * AsyncGeneratorWaitHandle - async generator-based async execution
50 * AwaitAllWaitHandle - wait handle representing a collection of
51 * WHs, does not propagate results
52 * ConditionWaitHandle - wait handle implementing condition variable
53 * RescheduleWaitHandle - wait handle that reschedules execution
54 * SleepWaitHandle - wait handle that finishes after a timeout
55 * ExternalThreadEventWaitHandle - thread-powered asynchronous execution
57 * A wait handle can be either synchronously joined (waited for the operation
58 * to finish) or passed in various contexts as a dependency and waited for
59 * asynchronously (such as using await mechanism of async function or
60 * passed to AwaitAllWaitHandle).
63 struct c_AsyncFunctionWaitHandle;
64 struct c_AsyncGeneratorWaitHandle;
65 struct c_AwaitAllWaitHandle;
66 struct c_ConditionWaitHandle;
67 struct c_RescheduleWaitHandle;
68 struct c_SleepWaitHandle;
69 struct c_ExternalThreadEventWaitHandle;
71 #define WAITHANDLE_CLASSOF(cn) \
72 static Class* classof() { \
73 static Class* cls = Unit::lookupClass(makeStaticString("HH\\" #cn)); \
74 return cls; \
77 #define WAITHANDLE_DTOR(cn) \
78 static void instanceDtor(ObjectData* obj, const Class*) { \
79 auto wh = wait_handle<c_##cn>(obj); \
80 wh->~c_##cn(); \
81 MM().objFree(obj, sizeof(c_##cn)); \
84 template<class T>
85 T* wait_handle(const ObjectData* obj) {
86 assert(obj->instanceof(T::classof()));
87 assert(obj->getAttribute(ObjectData::IsWaitHandle));
88 return static_cast<T*>(const_cast<ObjectData*>(obj));
91 struct c_WaitHandle : ObjectData {
92 WAITHANDLE_CLASSOF(WaitHandle);
93 WAITHANDLE_DTOR(WaitHandle);
95 enum class Kind : uint8_t {
96 Static,
97 AsyncFunction,
98 AsyncGenerator,
99 AwaitAll,
100 Condition,
101 Reschedule,
102 Sleep,
103 ExternalThreadEvent,
106 explicit c_WaitHandle(Class* cls, HeaderKind kind,
107 type_scan::Index tyindex) noexcept
108 : ObjectData(cls, NoInit{},
109 ObjectData::IsWaitHandle | ObjectData::NoDestructor,
110 kind),
111 m_tyindex(tyindex)
113 assert(type_scan::isKnownType(tyindex));
116 ~c_WaitHandle()
119 public:
120 static constexpr ptrdiff_t stateOff() {
121 return offsetof(c_WaitHandle, m_kind_state);
123 static constexpr ptrdiff_t resultOff() {
124 return offsetof(c_WaitHandle, m_resultOrException);
127 static c_WaitHandle* fromCell(Cell cell) {
128 return (
129 cell.m_type == KindOfObject &&
130 cell.m_data.pobj->getAttribute(ObjectData::IsWaitHandle)
131 ) ? static_cast<c_WaitHandle*>(cell.m_data.pobj) : nullptr;
133 static c_WaitHandle* fromCellAssert(Cell cell) {
134 assert(cell.m_type == KindOfObject);
135 assert(cell.m_data.pobj->getAttribute(ObjectData::IsWaitHandle));
136 return static_cast<c_WaitHandle*>(cell.m_data.pobj);
138 bool isFinished() const { return getState() <= STATE_FAILED; }
139 bool isSucceeded() const { return getState() == STATE_SUCCEEDED; }
140 bool isFailed() const { return getState() == STATE_FAILED; }
141 Cell getResult() const {
142 assert(isSucceeded());
143 return m_resultOrException;
145 ObjectData* getException() const {
146 assert(isFailed());
147 return m_resultOrException.m_data.pobj;
150 Kind getKind() const { return static_cast<Kind>(m_kind_state >> 4); }
151 uint8_t getState() const { return m_kind_state & 0x0F; }
152 static uint8_t toKindState(Kind kind, uint8_t state) {
153 assert((uint8_t)kind < 0x10 && state < 0x10);
154 return ((uint8_t)kind << 4) | state;
156 void setKindState(Kind kind, uint8_t state) {
157 m_kind_state = toKindState(kind, state);
159 void setContextVectorIndex(uint32_t idx) {
160 m_ctxVecIndex = idx;
163 c_AsyncFunctionWaitHandle* asAsyncFunction();
164 c_AsyncGeneratorWaitHandle* asAsyncGenerator();
165 c_AwaitAllWaitHandle* asAwaitAll();
166 c_ConditionWaitHandle* asCondition();
167 c_RescheduleWaitHandle* asReschedule();
168 c_ResumableWaitHandle* asResumable();
169 c_SleepWaitHandle* asSleep();
170 c_ExternalThreadEventWaitHandle* asExternalThreadEvent();
172 // The code in the TC will depend on the values of these constants.
173 // See emitAwait().
174 static const int8_t STATE_SUCCEEDED = 0; // completed with result
175 static const int8_t STATE_FAILED = 1; // completed with exception
177 void scan(type_scan::Scanner&) const;
179 private: // layout, ignoring ObjectData fields.
180 // 0 8 9 10 12
181 // [parentChain ][contextIdx][kind_state][tyindex][ctxVecIndex]
182 // [resultOrException.m_data][m_type] [aux]
183 static void checkLayout() {
184 constexpr auto data = offsetof(c_WaitHandle, m_resultOrException);
185 constexpr auto type = data + offsetof(TypedValue, m_type);
186 constexpr auto aux = data + offsetof(TypedValue, m_aux);
187 static_assert(offsetof(c_WaitHandle, m_parentChain) == data, "");
188 static_assert(offsetof(c_WaitHandle, m_contextIdx) == type, "");
189 static_assert(offsetof(c_WaitHandle, m_kind_state) < aux, "");
190 static_assert(offsetof(c_WaitHandle, m_ctxVecIndex) == aux, "");
193 protected:
194 union {
195 // STATE_SUCCEEDED || STATE_FAILED
196 Cell m_resultOrException;
198 // !STATE_SUCCEEDED && !STATE_FAILED
199 struct {
200 // WaitableWaitHandle: !STATE_SUCCEEDED && !STATE_FAILED
201 AsioBlockableChain m_parentChain;
203 // WaitableWaitHandle: !STATE_SUCCEEDED && !STATE_FAILED
204 context_idx_t m_contextIdx;
206 // valid in any WaitHandle state. doesn't overlap Cell fields.
207 uint8_t m_kind_state;
209 // type index of concrete waithandle for gc-scanning
210 type_scan::Index m_tyindex;
212 union {
213 // ExternalThreadEventWaitHandle: STATE_WAITING
214 // SleepWaitHandle: STATE_WAITING
215 uint32_t m_ctxVecIndex;
220 TYPE_SCAN_CUSTOM() {
221 if (isFinished()) {
222 scanner.scan(m_resultOrException);
223 } else {
224 scanner.scan(m_parentChain);
229 ///////////////////////////////////////////////////////////////////////////////
232 #endif // incl_HPHP_EXT_ASIO_WAIT_HANDLE_H_