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