-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Expand file tree
/
Copy pathext_await-all-wait-handle.h
More file actions
163 lines (137 loc) · 5.69 KB
/
Copy pathext_await-all-wait-handle.h
File metadata and controls
163 lines (137 loc) · 5.69 KB
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
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#pragma once
#include <vector>
#include "hphp/runtime/base/type-array.h"
#include "hphp/runtime/base/type-object.h"
#include "hphp/runtime/ext/asio/ext_waitable-wait-handle.h"
#include "hphp/runtime/ext/extension.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
// class AwaitAllWaitHandle
/**
* A wait handle that waits for a list of wait handles. The wait handle succeeds
* with null once all given wait handles are finished (succeeded or failed).
*/
struct c_AwaitAllWaitHandle final : c_WaitableWaitHandle,
SystemLib::ClassLoader<"HH\\AwaitAllWaitHandle"> {
using SystemLib::ClassLoader<"HH\\AwaitAllWaitHandle">::classof;
using SystemLib::ClassLoader<"HH\\AwaitAllWaitHandle">::className;
static void instanceDtor(ObjectData* obj, const Class*) {
auto wh = wait_handle<c_AwaitAllWaitHandle>(obj);
std::vector<c_AwaitAllWaitHandle*> queue = {wh};
for (std::size_t i = 0; i < queue.size(); i++) {
auto cur = queue[i];
for (int32_t j = 0; j < cur->m_cap; j++) {
auto cur_child = cur->m_children[j].m_child;
assertx(isFailed() || cur_child->isFinished());
if (cur_child->getKind() == Kind::AwaitAll) {
if (cur_child->decReleaseCheck()) {
queue.push_back(cur_child->asAwaitAll());
}
} else {
decRefObj(cur_child);
}
}
}
for (auto& cur : queue) {
auto const sz = cur->heapSize();
tl_heap->objFree(cur, sz);
}
}
explicit c_AwaitAllWaitHandle(unsigned cap = 0)
: c_WaitableWaitHandle(classof(), HeaderKind::AwaitAllWH,
type_scan::getIndexForMalloc<
c_AwaitAllWaitHandle,
type_scan::Action::WithSuffix<Node>
>())
, m_cap(cap)
, m_unfinished(cap - 1)
{}
~c_AwaitAllWaitHandle() {
assertx(isFinished());
for (int32_t i = 0; i < m_cap; i++) {
assertx(isFailed() || m_children[i].m_child->isFinished());
decRefObj(m_children[i].m_child);
}
}
public:
struct Node final {
static constexpr ptrdiff_t blockableOff() {
return offsetof(Node, m_blockable);
}
uint32_t getChildIdx() {
return m_index;
}
inline c_AwaitAllWaitHandle* getWaitHandle() {
return reinterpret_cast<c_AwaitAllWaitHandle*>(const_cast<char*>(
reinterpret_cast<const char*>(this - getChildIdx())
- c_AwaitAllWaitHandle::childrenOff()));
}
bool isFirstUnfinishedChild() {
return getChildIdx() == getWaitHandle()->m_unfinished;
}
void onUnblocked(std::vector<AsioBlockableChain>& worklist) {
getWaitHandle()->onUnblocked(getChildIdx(), worklist);
}
AsioBlockable m_blockable;
c_WaitableWaitHandle* m_child;
uint32_t m_index;
};
static constexpr ptrdiff_t childrenOff() {
return offsetof(c_AwaitAllWaitHandle, m_children);
}
String getName();
void onUnblocked(uint32_t idx, std::vector<AsioBlockableChain>& worklist);
c_WaitableWaitHandle* getChild();
template<typename T> void forEachChild(T fn);
size_t heapSize() const { return heapSize(m_cap); }
static size_t heapSize(unsigned count) {
return sizeof(c_AwaitAllWaitHandle) + count * sizeof(Node);
}
void scan(type_scan::Scanner&) const;
private:
template<typename Iter>
static Object Create(Iter iter);
static req::ptr<c_AwaitAllWaitHandle> Alloc(int32_t cnt);
void initialize(ContextStateIndex ctxStateIdx);
void markAsFinished(std::vector<AsioBlockableChain>& worklist);
void markAsFailed(const Object& exception, std::vector<AsioBlockableChain>& worklist);
void setState(uint8_t state) { setKindState(Kind::AwaitAll, state); }
// Construct an AAWH from an array-like without making layout assumptions.
static Object fromArrLike(const ArrayData* ad);
friend Object HHVM_STATIC_METHOD(AwaitAllWaitHandle, fromVec,
const Array& dependencies);
friend Object HHVM_STATIC_METHOD(AwaitAllWaitHandle, fromDict,
const Array& dependencies);
private:
uint32_t const m_cap; // how many children we have room for.
uint32_t m_unfinished; // index of the first unfinished child
Node m_children[0]; // allocated off the end
TYPE_SCAN_FLEXIBLE_ARRAY_FIELD(m_children);
public:
static const int8_t STATE_BLOCKED = 2;
};
inline c_AwaitAllWaitHandle* c_Awaitable::asAwaitAll() {
assertx(getKind() == Kind::AwaitAll);
return static_cast<c_AwaitAllWaitHandle*>(this);
}
///////////////////////////////////////////////////////////////////////////////
}
#define incl_HPHP_EXT_ASIO_AWAIT_ALL_WAIT_HANDLE_H_
#include "hphp/runtime/ext/asio/ext_await-all-wait-handle-inl.h"
#undef incl_HPHP_EXT_ASIO_AWAIT_ALL_WAIT_HANDLE_H_