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 —
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);
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.
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 |