26 template <
typename Context>
28 auto* thread = context.getCurrentThread();
29 return thread ?
static_cast<void*
>(thread) :
static_cast<void*
>(&context);
39 m_pDispatchOwner(
nullptr),
40 m_bDispatching(
false),
41 m_bDeferredRemoval(
false) {}
43 void prepare(
void* event, uint64_t deadline,
void* target) {
45 assert(!m_bDispatching);
47 m_Deadline = deadline;
49 m_pDispatchOwner =
nullptr;
50 m_bDeferredRemoval =
false;
57 uint64_t deadline()
const {
61 void* target()
const {
69 bool dispatching()
const {
70 return m_bDispatching;
73 bool deferredRemoval()
const {
74 return m_bDeferredRemoval;
84 m_pDispatchOwner =
nullptr;
85 m_bDispatching =
false;
86 m_bDeferredRemoval =
false;
93 void* m_pDispatchOwner;
95 bool m_bDeferredRemoval;
98 enum class RemovalDisposition {
106 RemovalDisposition disposition;
111 RtcAlarmQueue() : m_pFirst(nullptr), m_pLast(nullptr), m_pFree(nullptr) {}
113 Record* takeReusable() {
114 Record* record = m_pFree;
116 m_pFree = record->m_pNext;
117 record->m_pNext =
nullptr;
122 void add(Record* record) {
124 assert(record->m_pEvent);
125 assert(record->m_pTarget);
126 assert(!record->m_pNext);
127 assert(!record->m_bDispatching);
129 m_pLast->m_pNext = record;
136 uint64_t nextDeadline()
const {
137 uint64_t next = ~uint64_t(0);
138 for (Record* record = m_pFirst; record; record = record->m_pNext) {
139 if (!record->m_bDispatching && record->m_Deadline < next) {
140 next = record->m_Deadline;
146 Record* claimDue(uint64_t now,
void* owner) {
148 for (Record* record = m_pFirst; record; record = record->m_pNext) {
149 if (!record->m_bDispatching && record->m_Deadline <= now) {
150 record->m_bDispatching =
true;
151 record->m_pDispatchOwner = owner;
158 Removal removeFirst(
void* event,
void* owner) {
159 Record* previous =
nullptr;
160 for (Record* record = m_pFirst; record; record = record->m_pNext) {
161 if (record->m_pEvent != event) {
165 if (record->m_bDispatching) {
166 if (record->m_pDispatchOwner == owner) {
167 record->m_bDeferredRemoval =
true;
168 return {RemovalDisposition::SelfDeferred,
nullptr, record->m_Deadline};
170 return {RemovalDisposition::RemoteInFlight,
nullptr, record->m_Deadline};
173 const uint64_t deadline = record->m_Deadline;
174 unlink(previous, record);
175 return {RemovalDisposition::Removed, record, deadline};
177 return {RemovalDisposition::NotFound,
nullptr, 0};
180 Record* removeAllQueued(
void* event,
void* owner,
bool& remoteInFlight,
bool& selfDeferred) {
181 Record* removed =
nullptr;
182 Record* removedTail =
nullptr;
183 Record* previous =
nullptr;
184 Record* record = m_pFirst;
186 Record* next = record->m_pNext;
187 if (record->m_pEvent != event) {
192 if (record->m_bDispatching) {
193 if (record->m_pDispatchOwner == owner) {
194 record->m_bDeferredRemoval =
true;
197 remoteInFlight =
true;
204 unlink(previous, record);
205 record->m_pNext =
nullptr;
207 removedTail->m_pNext = record;
211 removedTail = record;
217 bool hasRemoteInFlight(
void* event,
void* owner)
const {
218 for (Record* record = m_pFirst; record; record = record->m_pNext) {
219 if (record->m_pEvent == event && record->m_bDispatching &&
220 record->m_pDispatchOwner != owner) {
227 void completeDispatch(Record* record) {
229 assert(record->m_bDispatching);
230 Record* previous =
nullptr;
231 Record* candidate = m_pFirst;
232 while (candidate && candidate != record) {
233 previous = candidate;
234 candidate = candidate->m_pNext;
236 assert(candidate == record);
237 unlink(previous, record);
241 void recycleList(Record* records) {
243 Record* next = records->m_pNext;
244 records->m_pNext =
nullptr;
250 Record* detachActive() {
251 Record* records = m_pFirst;
257 Record* detachFree() {
258 Record* records = m_pFree;
263 size_t activeCount()
const {
265 for (Record* record = m_pFirst; record; record = record->m_pNext) {
271 size_t freeCount()
const {
273 for (Record* record = m_pFree; record; record = record->m_pNext) {
280 void unlink(Record* previous, Record* record) {
282 previous->m_pNext = record->m_pNext;
284 m_pFirst = record->m_pNext;
286 if (m_pLast == record) {
289 record->m_pNext =
nullptr;
292 void recycle(Record* record) {
294 record->m_pNext = m_pFree;