libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_blocking.h
1/*-
2 * Copyright (c) 2026, The XTC Project
3 * @stability stable
4 * Use of this source code is governed by the ISC License.
5 *
6 * src/inc/xtc_blocking.h
7 * Offload blocking work to a thread pool, parking the calling
8 * process instead of blocking the loop.
9 *
10 * A loop thread must never block in a syscall: doing so stalls
11 * every other process sharing that loop. But some work is
12 * unavoidably blocking -- file reads and fsync (regular files are
13 * not pollable), getaddrinfo, third-party libraries. xtc_blocking
14 * runs such a call on a dedicated pool thread and parks the
15 * calling process until it finishes, so the loop keeps running
16 * other work meanwhile.
17 *
18 * The pool thread wakes the parked process through its task waker.
19 * No file descriptor is used per call.
20 */
21
22#ifndef XTC_BLOCKING_H
23#define XTC_BLOCKING_H
24
25#include "xtc_export.h"
26
27#include "xtc.h"
28
29/*
30 * Run fn(arg) on a blocking-pool thread and park the calling process
31 * until it completes; fn's return value is stored in *out_result.
32 *
33 * Must be called from within a process / coroutine running on a loop.
34 * Called outside that context it runs fn synchronously on the current
35 * thread -- always correct, just not yielding. Returns XTC_OK once fn
36 * has run. On a loop fn never runs on the loop thread: XTC_E_AGAIN
37 * (offload queue full, 65536 waiting calls) or XTC_E_RESOURCE (no pool
38 * thread could start) are returned WITHOUT running fn.
39 *
40 * PUBLIC: int xtc_blocking_run __P((int (*)(void *), void *, int *));
41 */
42XTC_API int xtc_blocking_run(int (*fn)(void *), void *arg, int *out_result);
43
44/*
45 * Off-loop variant of xtc_blocking_run for a plain OS thread that is NOT
46 * a libxtc fiber (xtc_self() == none): offload fn(arg) to the pool and
47 * block the CALLING thread until it completes, instead of parking a
48 * fiber (which a bare thread cannot do). fn runs
49 * on a pool worker, not inline on the caller.
50 *
51 * It is still synchronous from the caller's view (it blocks the calling
52 * thread until fn completes) and does NOT shorten any lock held across
53 * the call -- it moves the syscall off the caller thread, it does not
54 * let a non-fiber caller do other work meanwhile. To keep serving
55 * other multiplexed tasks during a blocking call, make those tasks
56 * fibers on a loop and use xtc_blocking_run (which yields). Returns
57 * XTC_E_INVAL if fn is NULL or if called from a fiber/loop process
58 * (use xtc_blocking_run there); XTC_E_AGAIN / XTC_E_RESOURCE as for
59 * xtc_blocking_run, without running fn.
60 *
61 * PUBLIC: int xtc_blocking_run_off_loop __P((int (*)(void *), void *, int *));
62 */
63XTC_API int xtc_blocking_run_off_loop(int (*fn)(void *), void *arg,
64 int *out_result);
65
66/*
67 * Fire-and-forget variant: hand fn(arg) to the offload pool and return
68 * immediately, without waiting for or collecting the result. Never
69 * parks, so it is callable from any context (e.g. prefetch/read-ahead).
70 * The caller owns arg's lifetime until fn runs (or has fn free it);
71 * there is no completion signal. XTC_E_AGAIN (queue full),
72 * XTC_E_RESOURCE (no pool thread) or XTC_E_NOMEM: fn was not queued.
73 *
74 * PUBLIC: int xtc_blocking_submit __P((int (*)(void *), void *));
75 */
76XTC_API int xtc_blocking_submit(int (*fn)(void *), void *arg);
77
78/*
79 * Pin the pool to a fixed size (worker threads), overriding the
80 * automatic default. Must be called before the first xtc_blocking_run
81 * / xtc_blocking_submit; later calls return XTC_E_INVAL (too late).
82 *
83 * By DEFAULT the pool auto-sizes: it starts with a CPU-scaled number of
84 * workers (max(4, online CPUs), capped at 64) and grows on demand up to
85 * 64 when work queues up faster than idle workers can take it, so the
86 * offload path is not an artificial bottleneck on a large host nor
87 * over-provisioned on a small one. Setting an explicit size disables
88 * the growth and fixes the pool at exactly that many threads.
89 *
90 * PUBLIC: int xtc_blocking_pool_size __P((int));
91 */
92XTC_API int xtc_blocking_pool_size(int nthreads);
93
94/*
95 * Stop the pool, joining its threads. Idempotent; for orderly
96 * shutdown and leak-checked test runs. A new xtc_blocking_run after
97 * shutdown restarts the pool.
98 *
99 * PUBLIC: void xtc_blocking_shutdown __P((void));
100 */
101XTC_API void xtc_blocking_shutdown(void);
102
103#endif /* XTC_BLOCKING_H */