libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_stream.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_stream.h
7 * Async streams: a lazy, pull-based sequence of values with
8 * composable combinators (map, filter, for_each). A stream is
9 * nothing more than a next() function that produces the next value
10 * (or signals end-of-stream), plus a small vtable so combinators can
11 * wrap one stream in another without materializing the whole
12 * sequence -- the Elixir Stream / Rust Iterator shape.
13 *
14 * Pull-based composes naturally with the demand channel (R9): a
15 * consumer pulls one value at a time, so a slow map/filter stage
16 * exerts backpressure just by pulling more slowly. Use
17 * xtc_stream_from_demand to turn an xtc_chan_demand into a stream.
18 *
19 * Values are void*; the stream never owns them (it neither copies
20 * nor frees). A combinator's transform decides ownership.
21 */
22
23#ifndef XTC_STREAM_H
24#define XTC_STREAM_H
25
26#include "xtc_export.h"
27
28#include <stddef.h>
29
30#include "xtc.h"
31#include "xtc_chan.h"
32
33typedef struct xtc_stream xtc_stream_t;
34
35/*
36 * Pull one value. On XTC_OK, *out holds the next value. Returns
37 * XTC_E_NOTFOUND at end-of-stream, XTC_E_AGAIN if no value is available
38 * yet but the stream is not finished (the caller should retry, e.g.
39 * after a demand-channel item arrives), or another XTC_E_* on error.
40 */
41typedef int (*xtc_stream_next_fn)(void *ctx, void **out);
42
43/*
44 * PUBLIC: int xtc_stream_create __P((xtc_stream_next_fn, void *, xtc_stream_t **));
45 * PUBLIC: void xtc_stream_destroy __P((xtc_stream_t *));
46 * PUBLIC: int xtc_stream_next __P((xtc_stream_t *, void **));
47 * PUBLIC: int xtc_stream_map __P((xtc_stream_t *, void *(*)(void *, void *), void *, xtc_stream_t **));
48 * PUBLIC: int xtc_stream_filter __P((xtc_stream_t *, int (*)(void *, void *), void *, xtc_stream_t **));
49 * PUBLIC: int xtc_stream_for_each __P((xtc_stream_t *, int (*)(void *, void *), void *));
50 * PUBLIC: int xtc_stream_from_demand __P((xtc_chan_demand_t *, xtc_stream_t **));
51 */
52
53/* Create a stream from a next() function and its context. */
54XTC_API int xtc_stream_create(xtc_stream_next_fn next, void *ctx,
55 xtc_stream_t **out);
56
57/* Destroy a stream. Destroying a combinator stream (map/filter) also
58 * destroys the source stream it wraps, recursively; destroy only the
59 * outermost stream. Does not touch the underlying demand channel of a
60 * from_demand stream (the caller owns that). */
61XTC_API void xtc_stream_destroy(xtc_stream_t *s);
62
63/* Pull the next value. See xtc_stream_next_fn for the return codes. */
64XTC_API int xtc_stream_next(xtc_stream_t *s, void **out);
65
66/* map: each pulled value v becomes fn(v, user). Lazy: fn runs only when
67 * the resulting stream is pulled. The new stream OWNS `s`. */
68XTC_API int xtc_stream_map(xtc_stream_t *s,
69 void *(*fn)(void *v, void *user), void *user,
70 xtc_stream_t **out);
71
72/* filter: values for which pred(v, user) returns 0 are skipped. The new
73 * stream OWNS `s`. */
74XTC_API int xtc_stream_filter(xtc_stream_t *s,
75 int (*pred)(void *v, void *user), void *user,
76 xtc_stream_t **out);
77
78/* Drain the stream, calling fn(v, user) for each value until
79 * end-of-stream. A nonzero fn return stops early and is returned. An
80 * XTC_E_AGAIN from the source is treated as "retry": for_each spins on
81 * it, so use it only with a source that will eventually produce or
82 * finish (e.g. a fully-buffered demand channel that has been closed). */
83XTC_API int xtc_stream_for_each(xtc_stream_t *s,
84 int (*fn)(void *v, void *user), void *user);
85
86/* Adapt a demand channel into a stream: each pull grants one unit of
87 * demand and returns the next buffered item (XTC_E_AGAIN until one
88 * arrives, XTC_E_NOTFOUND once the channel is closed and drained). */
89XTC_API int xtc_stream_from_demand(xtc_chan_demand_t *ch, xtc_stream_t **out);
90
91#endif /* XTC_STREAM_H */