libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_orc.h
1/*-
2 * Copyright (c) 2026, The XTC Project
3 * Use of this source code is governed by the ISC License.
4 *
5 * src/inc/xtc_orc.h
6 * L4 orchestration: supervisor. M10 ships ONE_FOR_ONE strategy
7 * with restart intensity (max-N-restarts-per-W-seconds). The
8 * other strategies (one_for_all, rest_for_one, simple_one_for_one)
9 * and the gen_server / app / registry layer arrive in M10.5.
10 *
11 * A supervisor is itself an xtc_proc that monitors its children
12 * and acts on their DOWN messages. Restart intensity is enforced
13 * by counting child deaths in a sliding window; if the rate
14 * exceeds max_restarts/period_ns, the supervisor exits up the
15 * tree.
16 */
17
18#ifndef XTC_ORC_H
19#define XTC_ORC_H
20
21#include "xtc_export.h"
22
23#include <stdint.h>
24
25#include "xtc.h"
26#include "xtc_loop.h"
27#include "xtc_proc.h"
28
29/*
30 * Restart strategies. M10 implements ONE_FOR_ONE; the others have
31 * named slots so callers can configure for the future and get a
32 * clear XTC_E_NOSYS for an unrecognized strategy value. All four
33 * strategies below are implemented.
34 */
35typedef enum xtc_restart_strategy {
36 XTC_SUP_ONE_FOR_ONE = 0,
37 XTC_SUP_ONE_FOR_ALL = 1, /* M10.5 */
38 XTC_SUP_REST_FOR_ONE = 2, /* M10.5 */
39 XTC_SUP_SIMPLE_OFO = 3 /* M10.5 */
40} xtc_restart_strategy_t;
41
42typedef enum xtc_restart_policy {
43 XTC_RESTART_PERMANENT = 0, /* always restart on exit */
44 XTC_RESTART_TRANSIENT = 1, /* restart only on abnormal exit */
45 XTC_RESTART_TEMPORARY = 2 /* never restart */
46} xtc_restart_policy_t;
47
48/* Forward declaration: the L2 multi-loop executor (xtc_exec.h). A
49 * supervisor may be given one so it places children across loops and
50 * owns the executor's stop on its own exit. */
51struct xtc_exec;
52
53typedef struct xtc_child_spec {
54 const char *name; /* optional, for logs */
55 xtc_proc_fn fn;
56 void *arg;
57 xtc_restart_policy_t policy;
58 size_t mailbox_cap; /* 0 = default */
59 int loop; /* exec loop index to place this
60 * child on (only when the supervisor
61 * has an exec); 0 = loop 0 */
63
64typedef struct xtc_sup_opts {
65 xtc_restart_strategy_t strategy;
66 int max_restarts; /* default 3 */
67 int64_t period_ns; /* default 5 s */
68 struct xtc_exec *exec; /* optional: place children
69 * across its loops and stop
70 * it when the supervisor exits;
71 * NULL = single-loop */
72 int max_children; /* 0 = unbounded; > 0 caps the
73 * dynamic child count
74 * (xtc_sup_add_child returns
75 * XTC_E_RESOURCE at the cap) --
76 * the simple_one_for_one pool
77 * bound */
79
80#define XTC_SUP_OPTS_DEFAULT { \
81 .strategy = XTC_SUP_ONE_FOR_ONE, \
82 .max_restarts = 3, \
83 .period_ns = 5LL * 1000 * 1000 * 1000, \
84 .exec = NULL, \
85 .max_children = 0 \
86}
87
88typedef struct xtc_supervisor xtc_supervisor_t;
89
90/*
91 * PUBLIC: int xtc_sup_start __P((xtc_loop_t *, const xtc_sup_opts_t *, const xtc_child_spec_t *, int, xtc_supervisor_t **));
92 * PUBLIC: int xtc_sup_add_child __P((xtc_supervisor_t *, const xtc_child_spec_t *, xtc_pid_t *));
93 * PUBLIC: int xtc_sup_stop __P((xtc_supervisor_t *));
94 * PUBLIC: int xtc_sup_n_children __P((const xtc_supervisor_t *));
95 * PUBLIC: int xtc_sup_n_alive __P((const xtc_supervisor_t *));
96 * PUBLIC: int xtc_sup_n_restarts __P((const xtc_supervisor_t *));
97 * PUBLIC: int xtc_sup_alive __P((const xtc_supervisor_t *));
98 */
99
100/*
101 * Start a supervisor on `loop` with `n_children` initial children.
102 * The supervisor itself runs as a process; the returned handle lets
103 * callers query/stop it from outside.
104 */
105XTC_API int xtc_sup_start(xtc_loop_t *loop,
106 const xtc_sup_opts_t *opts,
107 const xtc_child_spec_t *children,
108 int n_children,
109 xtc_supervisor_t **out_sup);
110
111/* Ask the supervisor to terminate. Non-blocking; returns immediately
112 * after setting the flag and sending a kick. Children get DOWN'd as
113 * the supervisor processes its mailbox; supervisor exits.
114 *
115 * Safe to call from any thread, multiple times. */
116XTC_API int xtc_sup_stop(xtc_supervisor_t *sup);
117
118/* Dynamically add a child to a running supervisor (the
119 * SIMPLE_ONE_FOR_ONE pattern: a pool of identical children spawned on
120 * demand). Routed through the supervisor proc so it owns the
121 * monitor; returns the new child's pid. Must be called from within a
122 * proc (it awaits the supervisor's reply). Keep spec->name alive for
123 * the child's lifetime. */
124XTC_API int xtc_sup_add_child(xtc_supervisor_t *sup, const xtc_child_spec_t *spec,
125 xtc_pid_t *out_pid);
126
127/* Wait for the supervisor to actually exit, then free its handle.
128 * Must be called from outside the supervisor's loop thread.
129 * timeout_ns < 0 = forever, 0 = poll-once. After a successful join
130 * the handle is invalid. */
131int xtc_sup_join(xtc_supervisor_t *sup, int64_t timeout_ns);
132
133XTC_API int xtc_sup_n_children(const xtc_supervisor_t *sup);
134XTC_API int xtc_sup_n_alive(const xtc_supervisor_t *sup);
135XTC_API int xtc_sup_n_restarts(const xtc_supervisor_t *sup);
136XTC_API int xtc_sup_alive(const xtc_supervisor_t *sup);
137
138#endif /* XTC_ORC_H */