Sometimes it's not feasible to rewrite blocking code so that it plays nice with the coro.Scheduler.
In that kind of scenario it is possible to use coro.ThreadPool to allow tasks to yield until blocking code
finishes on a worker thread.
fn blockingCode() u32 {
std.posix.nanosleep(1, 0);
return 69;
}
fn task(pool: *ThreadPool) !void {
const ret = try pool.yieldForCompletion(blockingCode, .{});
try std.testing.expectEqual(69, ret);
}
var scheduler = try Scheduler.init(std.testing.allocator, .{});
defer scheduler.deinit();
var pool: ThreadPool = try ThreadPool.init(std.testing.allocator, .{});
defer pool.deinit(); // pool must always be destroyed before scheduler
_ = try scheduler.spawn(task, .{&pool}, .{});
// Or alternatively, which does the same as above
_ = try pool.spawnForCompletion(&scheduler, blockingCode, .{});
try scheduler.run(.wait);