tmc::fork_group::fork_clang()

tmc::fork_group::fork_clang()#

tmc::fork_group::fork_clang() is a HALO-optimized method for forking awaitables in a fork_group. It uses the [[clang::coro_await_elidable_argument]] attribute when compiled with Clang 20+.

For HALO to work, fork_clang() must be awaited directly as a prvalue in a co_await expression.

// HALO: fork_clang() is directly awaited for each task
auto fg = tmc::fork_group<3, int>();
co_await fg.fork_clang(task_int(5));
co_await fg.fork_clang(task_int(6));
co_await fg.fork_clang(task_int(7));
auto results = co_await std::move(fg);

// Non-HALO: fork() without HALO attributes
auto fg = tmc::fork_group<3, int>();
fg.fork(task_int(8));
fg.fork(task_int(9));
fg.fork(task_int(10));
auto results = co_await std::move(fg);

WARNING: Do not use fork_group::fork_clang() in a loop, as Clang will try to reuse the same allocation for multiple active coroutines, causing crashes.

// fork_group::fork_clang() in a loop will cause a segfault!
// Clang erroneously tries to use the same allocation for all subtasks
auto fg = tmc::fork_group<3, int>();
for (size_t i = 0; i < fg.capacity(); i++) {
  co_await fg.fork_clang(task_int(i));
}
auto results = co_await std::move(fg);

// Correct: Use fork() without HALO attributes in a loop - works fine
auto fg = tmc::fork_group<3, int>();
for (size_t i = 0; i < fg.capacity(); i++) {
  fg.fork(task_int(i));
}
auto results = co_await std::move(fg);

Main Documentation#

For full documentation on tmc::fork_group, including the non-HALO .fork() method, see tmc::fork_group.