xtc_chan(3)
---xtc_chan(3)
typed channels for cross-task message passing
| XTC_CHAN(3) | Library Functions Manual | XTC_CHAN(3) |
NAME
xtc_chan_oneshot,
xtc_chan_oneshot_create,
xtc_chan_oneshot_destroy,
xtc_chan_oneshot_send,
xtc_chan_oneshot_try_recv,
xtc_chan_oneshot_set_waker,
xtc_chan_mpsc,
xtc_chan_mpsc_create,
xtc_chan_mpsc_destroy,
xtc_chan_mpsc_try_send,
xtc_chan_mpsc_try_recv,
xtc_chan_mpsc_set_waker,
xtc_chan_mpsc_close,
xtc_chan_mpsc_len,
xtc_chan_mpmc,
xtc_chan_mpmc_create,
xtc_chan_mpmc_destroy,
xtc_chan_mpmc_try_send,
xtc_chan_mpmc_try_recv,
xtc_chan_mpmc_close,
xtc_chan_mpmc_len,
xtc_chan_watch,
xtc_chan_watch_create,
xtc_chan_watch_destroy,
xtc_chan_watch_send,
xtc_chan_watch_recv,
xtc_chan_broadcast,
xtc_chan_broadcast_create,
xtc_chan_broadcast_destroy,
xtc_chan_broadcast_send,
xtc_chan_broadcast_subscribe,
xtc_chan_broadcast_unsubscribe,
xtc_chan_broadcast_recv,
xtc_chan_demand_create,
xtc_chan_demand_destroy,
xtc_chan_demand_ask,
xtc_chan_demand_send,
xtc_chan_demand_try_recv,
xtc_chan_demand_outstanding,
xtc_chan_demand_len,
xtc_chan_demand_set_producer_waker,
xtc_chan_demand_set_consumer_waker,
xtc_chan_demand_close —
typed channels for cross-task message passing
SYNOPSIS
#include <xtc.h>
#include <xtc_chan.h>
int
xtc_chan_oneshot_create(xtc_res_t
*res, xtc_chan_oneshot_t
**out);
void
xtc_chan_oneshot_destroy(xtc_chan_oneshot_t
*c);
int
xtc_chan_oneshot_send(xtc_chan_oneshot_t
*c, void *msg);
int
xtc_chan_oneshot_try_recv(xtc_chan_oneshot_t
*c, void
**out);
int
xtc_chan_oneshot_set_waker(xtc_chan_oneshot_t
*c, const xtc_waker_t
*w);
int
xtc_chan_mpsc_create(xtc_res_t
*res, size_t
capacity, xtc_chan_mpsc_t
**out);
void
xtc_chan_mpsc_destroy(xtc_chan_mpsc_t
*c);
int
xtc_chan_mpsc_try_send(xtc_chan_mpsc_t
*c, void *msg);
int
xtc_chan_mpsc_try_recv(xtc_chan_mpsc_t
*c, void
**out);
int
xtc_chan_mpsc_set_waker(xtc_chan_mpsc_t
*c, const xtc_waker_t
*w);
int
xtc_chan_mpsc_close(xtc_chan_mpsc_t
*c);
size_t
xtc_chan_mpsc_len(const
xtc_chan_mpsc_t *c);
int
xtc_chan_mpmc_create(xtc_res_t
*res, size_t
capacity, xtc_chan_mpmc_t
**out);
void
xtc_chan_mpmc_destroy(xtc_chan_mpmc_t
*c);
int
xtc_chan_mpmc_try_send(xtc_chan_mpmc_t
*c, void *msg);
int
xtc_chan_mpmc_try_recv(xtc_chan_mpmc_t
*c, void
**out);
int
xtc_chan_mpmc_close(xtc_chan_mpmc_t
*c);
size_t
xtc_chan_mpmc_len(const
xtc_chan_mpmc_t *c);
int
xtc_chan_watch_create(xtc_res_t
*res, xtc_chan_watch_t
**out);
void
xtc_chan_watch_destroy(xtc_chan_watch_t
*c);
int
xtc_chan_watch_send(xtc_chan_watch_t
*c, void
*value);
int
xtc_chan_watch_recv(xtc_chan_watch_t
*c, void
**out);
int
xtc_chan_broadcast_create(xtc_res_t
*res, size_t
capacity,
xtc_chan_broadcast_t
**out);
void
xtc_chan_broadcast_destroy(xtc_chan_broadcast_t
*c);
int
xtc_chan_broadcast_send(xtc_chan_broadcast_t
*c, void *msg);
int
xtc_chan_broadcast_subscribe(xtc_chan_broadcast_t
*c,
xtc_chan_broadcast_recv_t
**out_recv);
void
xtc_chan_broadcast_unsubscribe(xtc_chan_broadcast_recv_t
*r);
int
xtc_chan_broadcast_recv(xtc_chan_broadcast_recv_t
*r, void **out,
int *lagged);
int
xtc_chan_demand_create(xtc_res_t
*res, size_t
capacity,
xtc_chan_demand_t
**out);
void
xtc_chan_demand_destroy(xtc_chan_demand_t
*c);
int
xtc_chan_demand_ask(xtc_chan_demand_t
*c, size_t n);
int
xtc_chan_demand_send(xtc_chan_demand_t
*c, void *msg);
int
xtc_chan_demand_try_recv(xtc_chan_demand_t
*c, void
**out);
size_t
xtc_chan_demand_outstanding(const
xtc_chan_demand_t *c);
size_t
xtc_chan_demand_len(const
xtc_chan_demand_t *c);
int
xtc_chan_demand_set_producer_waker(xtc_chan_demand_t
*c, const xtc_waker_t
*w);
int
xtc_chan_demand_set_consumer_waker(xtc_chan_demand_t
*c, const xtc_waker_t
*w);
int
xtc_chan_demand_close(xtc_chan_demand_t
*c);
DESCRIPTION
xtc_chan provides typed channel primitives
for cross-task / cross-process / cross-thread message passing. Each channel
kind has different fan-in / fan-out semantics:
- oneshot
- A single message; one sender, one receiver. Used for request / reply
patterns, one-shot futures.
xtc_chan_oneshot_create() andxtc_chan_oneshot_destroy() manage the channel;xtc_chan_oneshot_send() delivers the single message;xtc_chan_oneshot_try_recv() polls for it; andxtc_chan_oneshot_set_waker() registers an xtc_waker_t for async readiness notification. - mpsc
- Multiple producers, single consumer. Bounded ring buffer. Lock- free
producer side using sequence-number CAS; consumer needs no
synchronisation.
xtc_chan_mpsc_create() takes a capacity;xtc_chan_mpsc_try_send() andxtc_chan_mpsc_try_recv() move messages without parking;xtc_chan_mpsc_set_waker() arms an async waker;xtc_chan_mpsc_close() marks the channel closed; andxtc_chan_mpsc_len() reports the queued count.xtc_chan_mpsc_destroy() frees it. - mpmc
- Multiple producers, multiple consumers. Bounded ring buffer serialising
both sides via per-slot sequence numbers (Vyukov-style queue).
xtc_chan_mpmc_create(),xtc_chan_mpmc_try_send(),xtc_chan_mpmc_try_recv(),xtc_chan_mpmc_close(),xtc_chan_mpmc_len(), andxtc_chan_mpmc_destroy() mirror the MPSC entry points. - watch
- Single-producer, multi-consumer of latest-value-only state. Useful for
config that may change while readers want the current view.
xtc_chan_watch_create() andxtc_chan_watch_destroy() manage the channel;xtc_chan_watch_send() publishes a new latest value; andxtc_chan_watch_recv() reads the current value. - broadcast
- Multi-producer, multi-consumer fan-out. Each subscribed consumer sees
every message. Per-consumer lag tracking; slow consumers see their queue
fill and may drop.
xtc_chan_broadcast_create() andxtc_chan_broadcast_destroy() manage the channel;xtc_chan_broadcast_send() fans a message out;xtc_chan_broadcast_subscribe() andxtc_chan_broadcast_unsubscribe() add and remove a consumer cursor; andxtc_chan_broadcast_recv() reads the next message for a subscriber, reporting a lagged count of messages skipped when it fell behind. - demand
- Pull-based, the reactive-streams / GenStage backpressure primitive. The
consumer explicitly ASKS for n items with
xtc_chan_demand_ask(); the producer'sxtc_chan_demand_send() succeeds only while there is outstanding demand (returningXTC_E_AGAINwhen demand is exhausted or the buffer is full), so a fast producer cannot outrun a slow consumer -- backpressure is expressed as demand, not as a fixed buffer that drops or blocks. Delivered items still buffer up to capacity, and the consumer drains them withxtc_chan_demand_try_recv(), which does NOT itself grant demand -- the consumer sets its own high-water policy by callingxtc_chan_demand_ask().xtc_chan_demand_outstanding() andxtc_chan_demand_len() report the un-consumed demand and the buffered item count.xtc_chan_demand_set_producer_waker() fires when the consumer grants demand;xtc_chan_demand_set_consumer_waker() fires when the producer sends an item;xtc_chan_demand_close() closes the channel (buffered items still drain).
All channels are heap-allocated and reference-managed via the optional xtc_res_t accountant; passing one charges memory against the cap.
Ownership:
the sender transfers ownership of the message buffer to the receiver. After
xtc_chan_*_send()
returns XTC_OK, the sender must not free or further
mutate the buffer. The receiver is responsible for freeing.
INTEGRATION WITH xtc_proc
For BEAM-style mailboxes use xtc_proc(3) directly: every process has its own mailbox without any explicit channel allocation. Channels are for fan-in / fan-out patterns that don't fit the per-proc-mailbox model:
- A pool of N workers consuming from one MPSC queue.
- N producers feeding M consumers via MPMC.
- Config-change broadcasts via watch channels.
EXAMPLES
MPSC work queue:
xtc_chan_mpsc_t *q;
xtc_chan_mpsc_create(NULL, /* cap */ 1024, &q);
/* producer */
xtc_chan_mpsc_try_send(q, work_item);
/* consumer */
void *item;
if (xtc_chan_mpsc_try_recv(q, &item) == XTC_OK) {
handle(item);
free(item);
}
SEE ALSO
HISTORY
Appeared in xtc 0.1.
| May 28, 2026 | Debian |