xtc_stream(3)
---xtc_stream(3)
lazy pull-based async streams with combinators
| XTC_STREAM(3) | Library Functions Manual | XTC_STREAM(3) |
NAME
xtc_stream_create,
xtc_stream_destroy,
xtc_stream_next,
xtc_stream_map,
xtc_stream_filter,
xtc_stream_for_each,
xtc_stream_from_demand —
lazy pull-based async streams with combinators
LIBRARY
library “libxtc”
SYNOPSIS
#include
<xtc_stream.h>
int
xtc_stream_create(xtc_stream_next_fn
next, void *ctx,
xtc_stream_t **out);
void
xtc_stream_destroy(xtc_stream_t
*s);
int
xtc_stream_next(xtc_stream_t
*s, void
**out);
int
xtc_stream_map(xtc_stream_t
*s, void *(*fn)(void *,
void *), void
*user, xtc_stream_t
**out);
int
xtc_stream_filter(xtc_stream_t
*s, int (*pred)(void *,
void *), void
*user, xtc_stream_t
**out);
int
xtc_stream_for_each(xtc_stream_t
*s, int (*fn)(void *,
void *), void
*user);
int
xtc_stream_from_demand(xtc_chan_demand_t
*ch, xtc_stream_t
**out);
DESCRIPTION
An async stream is a lazy, pull-based sequence of values -- the
Elixir ‘Stream’ and Rust
‘Iterator’ shape. A stream is just a
next()
function that yields the next value or signals end-of-stream, wrapped so
combinators can layer transformations without materializing the whole
sequence. Pull-based composition means a slow downstream stage exerts
backpressure simply by pulling more slowly, which pairs directly with the
demand channel (xtc_chan(3)).
Values are void *; the stream never copies or frees them. A combinator's transform decides ownership.
xtc_stream_create()
builds a base stream from a next() function and its
context.
xtc_stream_next()
pulls one value: it writes *out and returns
XTC_OK, XTC_E_NOTFOUND at
end-of-stream, XTC_E_AGAIN if no value is ready yet
but the stream is not finished (retry), or another
XTC_E_* on error.
xtc_stream_map()
returns a stream in which each pulled value v becomes
fn(v,
user);
xtc_stream_filter()
returns a stream that skips values for which
pred(v,
user) is 0. Both are lazy and both OWN the source
stream, so destroying the combinator destroys the source; destroy only the
outermost stream.
xtc_stream_for_each()
drains a stream, calling
fn(v,
user) for each value until end-of-stream. A nonzero
fn() return stops early and is returned; an
XTC_E_AGAIN from the source is retried, so use
xtc_stream_for_each() only with a source that will
eventually produce or finish.
xtc_stream_from_demand()
adapts a demand channel into a stream: each pull grants one unit of demand
and returns the next buffered item. It does not own the channel.
RETURN VALUES
All functions except xtc_stream_destroy()
return XTC_OK or a negative
XTC_E_* code (see
xtc_stream_next() for its stream-specific
codes).
xtc_stream_destroy() returns no value; it
recursively destroys any wrapped source stream but never touches the demand
channel of a xtc_stream_from_demand() stream.
EXAMPLES
/* double the even numbers coming off a demand channel */
static int is_even(void *v, void *u) { (void)u; return (*(int*)v & 1)==0; }
static void *dbl(void *v, void *u) { (void)u; *(int*)v *= 2; return v; }
static int print_it(void *v, void *u) { (void)u; printf("%d\n",*(int*)v); return 0; }
xtc_stream_t *s, *f, *m;
xtc_stream_from_demand(ch, &s);
xtc_stream_filter(s, is_even, NULL, &f);
xtc_stream_map(f, dbl, NULL, &m);
xtc_stream_for_each(m, print_it, NULL);
xtc_stream_destroy(m); /* frees m -> f -> s */
SEE ALSO
| July 10, 2026 | Debian |