Skip to content

Commit 62fc3ea

Browse files
committed
api: minor optimizations for async runtime infrastructure
1 parent aa997dd commit 62fc3ea

1 file changed

Lines changed: 31 additions & 29 deletions

File tree

api/async.hpp

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class __jule_thread;
8383
// Historically, this field was a smart pointer.
8484
// However, due to a toolchain bug in Windows, it's supposed to be a trivial type.
8585
// See: https://github.com/mstorsjo/llvm-mingw/issues/541
86-
inline thread_local __jule_thread *__jule_ct = nullptr;
86+
inline constinit thread_local __jule_thread *__jule_ct = nullptr;
8787

8888
// Non-templated coroutine handle used by the runtime.
8989
// The runtime never needs promise-type information.
@@ -107,7 +107,7 @@ struct __jule_RetireNode
107107

108108
// One retire list per worker thread.
109109
// This is strictly thread-local and never shared.
110-
inline thread_local __jule_RetireNode *__jule_retireHead = nullptr;
110+
inline constinit thread_local __jule_RetireNode *__jule_retireHead = nullptr;
111111

112112
// Pushes a coroutine frame onto the retire list.
113113
static inline void __jule_retirePush(__jule_RetireNode &n, __jule_cHandle h) noexcept
@@ -130,6 +130,12 @@ static inline void __jule_retirePush(__jule_RetireNode &n, __jule_cHandle h) noe
130130
// Destroys all retired coroutine frames for the current worker thread.
131131
static inline void __jule_retireDrain(void) noexcept
132132
{
133+
// Fast-path: Mostly, there is nothing to retire.
134+
if (!__jule_retireHead) [[likely]]
135+
{
136+
return;
137+
}
138+
133139
__jule_RetireNode *list = __jule_retireHead;
134140
__jule_retireHead = nullptr;
135141
while (list)
@@ -168,7 +174,7 @@ struct __jule_TrampNode
168174
__jule_cHandle h{};
169175
};
170176

171-
inline thread_local __jule_TrampNode *__jule_trampHead = nullptr;
177+
inline constinit thread_local __jule_TrampNode *__jule_trampHead = nullptr;
172178

173179
// Enqueue using a persistent node (embedded in a promise or other stable storage).
174180
static inline void __jule_trampolineEnqueueNode(__jule_TrampNode &n, __jule_cHandle h) noexcept
@@ -197,10 +203,8 @@ static inline void __jule_trampolineRun(void) noexcept
197203
__jule_trampHead = n->next;
198204

199205
__jule_cHandle h = n->h;
200-
n->h = {};
201-
n->next = nullptr;
202206

203-
if (h && !h.done())
207+
if (h && !h.done()) [[likely]]
204208
{
205209
h.resume();
206210
}
@@ -245,9 +249,8 @@ class __jule_Async
245249
// Continuation coroutine (awaiter).
246250
__jule_cHandle continuation{};
247251

248-
// Persistent trampoline nodes (allocation-free).
249-
__jule_TrampNode self_node{};
250-
__jule_TrampNode cont_node{};
252+
// Persistent trampoline node (allocation-free).
253+
__jule_TrampNode tramp_node{};
251254

252255
__jule_Async<T> get_return_object(void) noexcept
253256
{
@@ -264,22 +267,22 @@ class __jule_Async
264267
{
265268
bool await_ready(void) noexcept { return false; }
266269

267-
__jule_cHandle await_suspend(std::coroutine_handle<promise_type> h) noexcept
270+
void await_suspend(std::coroutine_handle<promise_type> h) noexcept
268271
{
269272
auto &p = h.promise();
270273
if (p.continuation)
271274
{
272-
__jule_trampolineEnqueueNode(p.cont_node, p.continuation);
275+
__jule_trampolineEnqueueNode(p.tramp_node, p.continuation);
273276
}
274-
return std::noop_coroutine();
277+
return;
275278
}
276279

277280
void await_resume(void) noexcept {}
278281
};
279282

280283
Final final_suspend(void) noexcept { return {}; }
281284

282-
void unhandled_exception(void)
285+
void unhandled_exception(void) noexcept
283286
{
284287
// Jule does not propagate exceptions across coroutine boundaries.
285288
std::terminate();
@@ -326,16 +329,16 @@ class __jule_Async
326329
return h.done();
327330
}
328331

329-
__jule_cHandle await_suspend(__jule_cHandle caller) noexcept
332+
void await_suspend(__jule_cHandle caller) noexcept
330333
{
331334
auto &p = h.promise();
332335
p.continuation = caller;
333336

334337
// Enqueue task itself; do NOT symmetric-transfer into it.
335-
__jule_trampolineEnqueueNode(p.self_node, h);
338+
__jule_trampolineEnqueueNode(p.tramp_node, h);
336339

337340
// Return to scheduler boundary (no deep chaining).
338-
return std::noop_coroutine();
341+
return;
339342
}
340343

341344
T await_resume(void)
@@ -360,9 +363,8 @@ class __jule_VoidAsync
360363
{
361364
__jule_cHandle continuation{};
362365

363-
// Persistent trampoline nodes (allocation-free).
364-
__jule_TrampNode self_node{};
365-
__jule_TrampNode cont_node{};
366+
// Persistent trampoline node (allocation-free).
367+
__jule_TrampNode tramp_node{};
366368

367369
__jule_VoidAsync get_return_object(void) noexcept
368370
{
@@ -375,22 +377,22 @@ class __jule_VoidAsync
375377
{
376378
bool await_ready(void) noexcept { return false; }
377379

378-
__jule_cHandle await_suspend(std::coroutine_handle<promise_type> h) noexcept
380+
void await_suspend(std::coroutine_handle<promise_type> h) noexcept
379381
{
380382
auto &p = h.promise();
381383
if (p.continuation)
382384
{
383-
__jule_trampolineEnqueueNode(p.cont_node, p.continuation);
385+
__jule_trampolineEnqueueNode(p.tramp_node, p.continuation);
384386
}
385-
return std::noop_coroutine();
387+
return;
386388
}
387389

388390
void await_resume(void) noexcept {}
389391
};
390392

391393
Final final_suspend(void) noexcept { return {}; }
392394

393-
void unhandled_exception(void) { std::terminate(); }
395+
void unhandled_exception(void) noexcept { std::terminate(); }
394396
void return_void(void) noexcept {}
395397
};
396398

@@ -424,16 +426,16 @@ class __jule_VoidAsync
424426
return h.done();
425427
}
426428

427-
__jule_cHandle await_suspend(__jule_cHandle caller) noexcept
429+
void await_suspend(__jule_cHandle caller) noexcept
428430
{
429431
auto &p = h.promise();
430432
p.continuation = caller;
431433

432434
// Enqueue the task coroutine; do NOT symmetric-transfer.
433-
__jule_trampolineEnqueueNode(p.self_node, h);
435+
__jule_trampolineEnqueueNode(p.tramp_node, h);
434436

435437
// Return to scheduler boundary.
436-
return std::noop_coroutine();
438+
return;
437439
}
438440

439441
void await_resume(void) noexcept
@@ -465,19 +467,19 @@ class __jule_Coroutine
465467
{
466468
bool await_ready(void) noexcept { return false; }
467469

468-
__jule_cHandle await_suspend(std::coroutine_handle<promise_type> h) noexcept
470+
void await_suspend(std::coroutine_handle<promise_type> h) noexcept
469471
{
470472
auto &p = h.promise();
471473
__jule_retirePush(p.retire_node, h);
472-
return std::noop_coroutine();
474+
return;
473475
}
474476

475477
void await_resume(void) noexcept {}
476478
};
477479

478480
Final final_suspend(void) noexcept { return {}; }
479481

480-
void unhandled_exception(void) { std::terminate(); }
482+
void unhandled_exception(void) noexcept { std::terminate(); }
481483
void return_void(void) noexcept {}
482484
};
483485

0 commit comments

Comments
 (0)