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 <stdint.h>
22
23#include "xtc.h"
24#include "xtc_loop.h"
25#include "xtc_proc.h"
26
27/*
28 * Restart strategies. M10 implements ONE_FOR_ONE; the others have
29 * named slots so callers can configure for the future and get a
30 * clear XTC_E_NOSYS for an unrecognized strategy value. All four
31 * strategies below are implemented.
32 */
33typedef enum xtc_restart_strategy {
34 XTC_SUP_ONE_FOR_ONE = 0,
35 XTC_SUP_ONE_FOR_ALL = 1, /* M10.5 */
36 XTC_SUP_REST_FOR_ONE = 2, /* M10.5 */
37 XTC_SUP_SIMPLE_OFO = 3 /* M10.5 */
38} xtc_restart_strategy_t;
39
40typedef enum xtc_restart_policy {
41 XTC_RESTART_PERMANENT = 0, /* always restart on exit */
42 XTC_RESTART_TRANSIENT = 1, /* restart only on abnormal exit */
43 XTC_RESTART_TEMPORARY = 2 /* never restart */
44} xtc_restart_policy_t;
45
46/* Forward declaration: the L2 multi-loop executor (xtc_exec.h). A
47 * supervisor may be given one so it places children across loops and
48 * owns the executor's stop on its own exit. */
49struct xtc_exec;
50
51typedef struct xtc_child_spec {
52 const char *name; /* optional, for logs */
53 xtc_proc_fn fn;
54 void *arg;
55 xtc_restart_policy_t policy;
56 size_t mailbox_cap; /* 0 = default */
57 int loop; /* exec loop index to place this
58 * child on (only when the supervisor
59 * has an exec); 0 = loop 0 */
61
62typedef struct xtc_sup_opts {
63 xtc_restart_strategy_t strategy;
64 int max_restarts; /* default 3 */
65 int64_t period_ns; /* default 5 s */
66 struct xtc_exec *exec; /* optional: place children
67 * across its loops and stop
68 * it when the supervisor exits;
69 * NULL = single-loop */
70 int max_children; /* 0 = unbounded; > 0 caps the
71 * dynamic child count
72 * (xtc_sup_add_child returns
73 * XTC_E_RESOURCE at the cap) --
74 * the simple_one_for_one pool
75 * bound */
77
78#define XTC_SUP_OPTS_DEFAULT { \
79 .strategy = XTC_SUP_ONE_FOR_ONE, \
80 .max_restarts = 3, \
81 .period_ns = 5LL * 1000 * 1000 * 1000, \
82 .exec = NULL, \
83 .max_children = 0 \
84}
85
86typedef struct xtc_supervisor xtc_supervisor_t;
87
88/*
89 * PUBLIC: int xtc_sup_start __P((xtc_loop_t *, const xtc_sup_opts_t *, const xtc_child_spec_t *, int, xtc_supervisor_t **));
90 * PUBLIC: int xtc_sup_add_child __P((xtc_supervisor_t *, const xtc_child_spec_t *, xtc_pid_t *));
91 * PUBLIC: int xtc_sup_stop __P((xtc_supervisor_t *));
92 * PUBLIC: int xtc_sup_n_children __P((const xtc_supervisor_t *));
93 * PUBLIC: int xtc_sup_n_alive __P((const xtc_supervisor_t *));
94 * PUBLIC: int xtc_sup_n_restarts __P((const xtc_supervisor_t *));
95 * PUBLIC: int xtc_sup_alive __P((const xtc_supervisor_t *));
96 */
97
98/*
99 * Start a supervisor on `loop` with `n_children` initial children.
100 * The supervisor itself runs as a process; the returned handle lets
101 * callers query/stop it from outside.
102 */
103int xtc_sup_start(xtc_loop_t *loop,
104 const xtc_sup_opts_t *opts,
105 const xtc_child_spec_t *children,
106 int n_children,
107 xtc_supervisor_t **out_sup);
108
109/* Ask the supervisor to terminate. Non-blocking; returns immediately
110 * after setting the flag and sending a kick. Children get DOWN'd as
111 * the supervisor processes its mailbox; supervisor exits.
112 *
113 * Safe to call from any thread, multiple times. */
114int xtc_sup_stop(xtc_supervisor_t *sup);
115
116/* Dynamically add a child to a running supervisor (the
117 * SIMPLE_ONE_FOR_ONE pattern: a pool of identical children spawned on
118 * demand). Routed through the supervisor proc so it owns the
119 * monitor; returns the new child's pid. Must be called from within a
120 * proc (it awaits the supervisor's reply). Keep spec->name alive for
121 * the child's lifetime. */
122int xtc_sup_add_child(xtc_supervisor_t *sup, const xtc_child_spec_t *spec,
123 xtc_pid_t *out_pid);
124
125/* Wait for the supervisor to actually exit, then free its handle.
126 * Must be called from outside the supervisor's loop thread.
127 * timeout_ns < 0 = forever, 0 = poll-once. After a successful join
128 * the handle is invalid. */
129int xtc_sup_join(xtc_supervisor_t *sup, int64_t timeout_ns);
130
131int xtc_sup_n_children(const xtc_supervisor_t *sup);
132int xtc_sup_n_alive(const xtc_supervisor_t *sup);
133int xtc_sup_n_restarts(const xtc_supervisor_t *sup);
134int xtc_sup_alive(const xtc_supervisor_t *sup);
135
136#endif /* XTC_ORC_H */