Skip to content

Commit 7ed7164

Browse files
committed
++
1 parent 95222f5 commit 7ed7164

22 files changed

Lines changed: 363 additions & 717 deletions

File tree

c/README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Suitable for bare-metal and simple RTOS configurations.
7474
rx_cyclic_exec ce;
7575
rx_cyclic_exec_init(&ce);
7676
rx_cyclic_exec_add(&ce, &runtime.runtime);
77-
rx_cyclic_exec_run(&ce); /* never returns */
77+
rx_cyclic_exec_run(&ce); /* returns after rx_cyclic_exec_stop(&ce) */
7878
```
7979

8080
### `rx_coop_exec` — cooperative multi-rate
@@ -87,7 +87,7 @@ cooperative RTOS patterns.
8787
rx_coop_exec ce;
8888
rx_coop_exec_init(&ce);
8989
rx_coop_exec_add(&ce, &runtime.runtime);
90-
rx_coop_exec_run(&ce); /* never returns */
90+
rx_coop_exec_run(&ce); /* returns after rx_coop_exec_stop(&ce) */
9191
```
9292
9393
Multiple runtimes can be registered; the scheduler picks the earliest deadline across all of them.
@@ -107,9 +107,12 @@ The last node of the last runtime runs in the calling (main) thread.
107107
rx_thread_exec te;
108108
rx_thread_exec_init(&te);
109109
rx_thread_exec_add(&te, &runtime.runtime); /* one runtime: all nodes get threads */
110-
rx_thread_exec_run(&te); /* never returns */
110+
rx_thread_exec_run(&te); /* returns after rx_thread_exec_stop(&te) */
111111
```
112112

113+
Each executor also has an `rx_*_exec_on_stop()` hook for application/model
114+
shutdown logic that must run once before `rx_*_exec_run()` returns.
115+
113116
Multiple runtimes can be registered; each forms an independent barrier group:
114117

115118
```c
@@ -297,7 +300,7 @@ void app_main(void)
297300
298301
rx_coop_exec_init(&ce);
299302
rx_coop_exec_add(&ce, &rt.runtime);
300-
rx_coop_exec_run(&ce); /* never returns */
303+
rx_coop_exec_run(&ce); /* returns after rx_coop_exec_stop(&ce) */
301304
}
302305
```
303306

@@ -380,7 +383,7 @@ int main(void)
380383

381384
rx_coop_exec_init(&ce);
382385
rx_coop_exec_add(&ce, &rt.runtime);
383-
rx_coop_exec_run(&ce); /* never returns */
386+
rx_coop_exec_run(&ce); /* returns after rx_coop_exec_stop(&ce) */
384387

385388
return 0;
386389
}

c/examples/fsm/01-light/main_cli.c

Lines changed: 12 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// Copyright 2026 Jose M. Moya <jm.moya@upm.es>
22
// SPDX-License-Identifier: MIT
33

4-
#include <errno.h>
54
#include <stdio.h>
65
#include <stdlib.h>
7-
#include <time.h>
86

7+
#include "rxnet/coop.h"
98
#include "rxnet/fsm.h"
109

1110
#include "app_driver.h"
@@ -17,6 +16,7 @@
1716
#define LIGHT_C_GPIO 5
1817
#define BUTTON_A_GPIO 0
1918
#define BUTTON_B_GPIO 15
19+
#define PERIOD_US (10 * 1000)
2020

2121
typedef struct {
2222
const rx_fsm_machine *light_a_machine;
@@ -87,37 +87,8 @@ cmd_quit(rx_fsm_context *ctx, cli_machine_data *cli,
8787
exit(0);
8888
}
8989

90-
static struct timespec
91-
timespec_add_us(struct timespec t, long us)
92-
{
93-
t.tv_nsec += us * 1000L;
94-
while (t.tv_nsec >= 1000000000L) {
95-
t.tv_nsec -= 1000000000L;
96-
++t.tv_sec;
97-
}
98-
return t;
99-
}
100-
101-
static int
102-
timespec_compare(struct timespec a, struct timespec b)
103-
{
104-
if (a.tv_sec < b.tv_sec) {
105-
return -1;
106-
}
107-
if (a.tv_sec > b.tv_sec) {
108-
return 1;
109-
}
110-
if (a.tv_nsec < b.tv_nsec) {
111-
return -1;
112-
}
113-
if (a.tv_nsec > b.tv_nsec) {
114-
return 1;
115-
}
116-
return 0;
117-
}
118-
119-
int
120-
main(void)
90+
int
91+
main(void)
12192
{
12293
rx_fsm_runtime runtime;
12394
rx_fsm_machine light_a_machine;
@@ -131,9 +102,7 @@ main(void)
131102
.light_c_machine = &light_c_machine,
132103
};
133104
cli_machine_data cli_data;
134-
const long period_us = 10 * 1000;
135-
struct timespec now;
136-
struct timespec next_tick;
105+
rx_coop_exec ce;
137106

138107
if (rx_fsm_runtime_init(&runtime, 4) != 0) {
139108
fprintf(stderr, "rx_fsm_runtime_init failed\n");
@@ -159,10 +128,10 @@ main(void)
159128
}
160129
cli_fsm_create(&cli_machine, "cli", &cli_data);
161130

162-
if (rx_fsm_runtime_add_machine(&runtime, &light_a_machine, 0, 0) != 0 ||
163-
rx_fsm_runtime_add_machine(&runtime, &light_b_machine, 0, 0) != 0 ||
164-
rx_fsm_runtime_add_machine(&runtime, &light_c_machine, 0, 0) != 0 ||
165-
rx_fsm_runtime_add_machine(&runtime, &cli_machine, 0, 0) != 0) {
131+
if (rx_fsm_runtime_add_machine(&runtime, &light_a_machine, PERIOD_US, 0) != 0 ||
132+
rx_fsm_runtime_add_machine(&runtime, &light_b_machine, PERIOD_US, 0) != 0 ||
133+
rx_fsm_runtime_add_machine(&runtime, &light_c_machine, PERIOD_US, 0) != 0 ||
134+
rx_fsm_runtime_add_machine(&runtime, &cli_machine, PERIOD_US, 0) != 0) {
166135
fprintf(stderr, "rx_fsm_runtime_add_machine failed\n");
167136
rx_fsm_runtime_free(&runtime);
168137
return 1;
@@ -172,61 +141,9 @@ main(void)
172141
cmd_status(&runtime.context, &cli_data, "status", &app_data);
173142
cli_fsm_print_prompt(&cli_data);
174143

175-
if (clock_gettime(CLOCK_MONOTONIC, &next_tick) != 0) {
176-
fprintf(stderr, "clock_gettime failed\n");
177-
rx_fsm_runtime_free(&runtime);
178-
return 1;
179-
}
180-
next_tick = timespec_add_us(next_tick, period_us);
181-
182-
while (1) {
183-
if (rx_fsm_tick(&runtime) != 0) {
184-
fprintf(stderr, "rx_fsm_tick failed\n");
185-
break;
186-
}
187-
188-
if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
189-
fprintf(stderr, "clock_gettime failed\n");
190-
break;
191-
}
192-
193-
while (timespec_compare(now, next_tick) >= 0) {
194-
next_tick = timespec_add_us(next_tick, period_us);
195-
}
196-
197-
while (1) {
198-
struct timespec sleep_time = {
199-
.tv_sec = next_tick.tv_sec - now.tv_sec,
200-
.tv_nsec = next_tick.tv_nsec - now.tv_nsec,
201-
};
202-
203-
if (sleep_time.tv_nsec < 0) {
204-
sleep_time.tv_nsec += 1000000000L;
205-
--sleep_time.tv_sec;
206-
}
207-
208-
if (sleep_time.tv_sec < 0) {
209-
break;
210-
}
211-
212-
if (nanosleep(&sleep_time, NULL) == 0) {
213-
break;
214-
}
215-
216-
if (errno != EINTR) {
217-
fprintf(stderr, "nanosleep failed\n");
218-
break;
219-
}
220-
221-
if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
222-
fprintf(stderr, "clock_gettime failed\n");
223-
break;
224-
}
225-
}
226-
227-
next_tick = timespec_add_us(next_tick, period_us);
228-
}
144+
rx_coop_exec_init(&ce);
145+
rx_coop_exec_add(&ce, &runtime.runtime);
146+
rx_coop_exec_run(&ce); /* never returns */
229147

230-
rx_fsm_runtime_free(&runtime);
231148
return 0;
232149
}

c/examples/fsm/02-auto/main_cli.c

Lines changed: 9 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// Copyright 2026 Jose M. Moya <jm.moya@upm.es>
22
// SPDX-License-Identifier: MIT
33

4-
#include <errno.h>
54
#include <stdio.h>
65
#include <stdlib.h>
7-
#include <time.h>
86

7+
#include "rxnet/coop.h"
98
#include "rxnet/fsm.h"
109

1110
#include "app_driver.h"
@@ -179,35 +178,6 @@ cmd_quit(rx_fsm_context *ctx, cli_machine_data *cli,
179178
exit(0);
180179
}
181180

182-
static struct timespec
183-
timespec_add_us(struct timespec t, long us)
184-
{
185-
t.tv_nsec += us * 1000L;
186-
while (t.tv_nsec >= 1000000000L) {
187-
t.tv_nsec -= 1000000000L;
188-
++t.tv_sec;
189-
}
190-
return t;
191-
}
192-
193-
static int
194-
timespec_compare(struct timespec a, struct timespec b)
195-
{
196-
if (a.tv_sec < b.tv_sec) {
197-
return -1;
198-
}
199-
if (a.tv_sec > b.tv_sec) {
200-
return 1;
201-
}
202-
if (a.tv_nsec < b.tv_nsec) {
203-
return -1;
204-
}
205-
if (a.tv_nsec > b.tv_nsec) {
206-
return 1;
207-
}
208-
return 0;
209-
}
210-
211181
int
212182
main(void)
213183
{
@@ -223,8 +193,7 @@ main(void)
223193
.auto_c_machine = &auto_c_machine,
224194
};
225195
cli_machine_data cli_data;
226-
struct timespec now;
227-
struct timespec next_tick;
196+
rx_coop_exec ce;
228197

229198
if (rx_fsm_runtime_init(&runtime, 4) != 0) {
230199
fprintf(stderr, "rx_fsm_runtime_init failed\n");
@@ -251,10 +220,10 @@ main(void)
251220
}
252221
cli_fsm_create(&cli_machine, "cli", &cli_data);
253222

254-
if (rx_fsm_runtime_add_machine(&runtime, &auto_a_machine, 0, 0) != 0 ||
255-
rx_fsm_runtime_add_machine(&runtime, &auto_b_machine, 0, 0) != 0 ||
256-
rx_fsm_runtime_add_machine(&runtime, &auto_c_machine, 0, 0) != 0 ||
257-
rx_fsm_runtime_add_machine(&runtime, &cli_machine, 0, 0) != 0) {
223+
if (rx_fsm_runtime_add_machine(&runtime, &auto_a_machine, PERIOD_US, 0) != 0 ||
224+
rx_fsm_runtime_add_machine(&runtime, &auto_b_machine, PERIOD_US, 0) != 0 ||
225+
rx_fsm_runtime_add_machine(&runtime, &auto_c_machine, PERIOD_US, 0) != 0 ||
226+
rx_fsm_runtime_add_machine(&runtime, &cli_machine, PERIOD_US, 0) != 0) {
258227
fprintf(stderr, "rx_fsm_runtime_add_machine failed\n");
259228
rx_fsm_runtime_free(&runtime);
260229
return 1;
@@ -264,61 +233,9 @@ main(void)
264233
cmd_status(&runtime.context, &cli_data, "status", &app_data);
265234
cli_fsm_print_prompt(&cli_data);
266235

267-
if (clock_gettime(CLOCK_MONOTONIC, &next_tick) != 0) {
268-
fprintf(stderr, "clock_gettime failed\n");
269-
rx_fsm_runtime_free(&runtime);
270-
return 1;
271-
}
272-
next_tick = timespec_add_us(next_tick, PERIOD_US);
273-
274-
while (1) {
275-
if (rx_fsm_tick(&runtime) != 0) {
276-
fprintf(stderr, "rx_fsm_tick failed\n");
277-
break;
278-
}
279-
280-
if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
281-
fprintf(stderr, "clock_gettime failed\n");
282-
break;
283-
}
284-
285-
while (timespec_compare(now, next_tick) >= 0) {
286-
next_tick = timespec_add_us(next_tick, PERIOD_US);
287-
}
288-
289-
while (1) {
290-
struct timespec sleep_time = {
291-
.tv_sec = next_tick.tv_sec - now.tv_sec,
292-
.tv_nsec = next_tick.tv_nsec - now.tv_nsec,
293-
};
294-
295-
if (sleep_time.tv_nsec < 0) {
296-
sleep_time.tv_nsec += 1000000000L;
297-
--sleep_time.tv_sec;
298-
}
299-
300-
if (sleep_time.tv_sec < 0) {
301-
break;
302-
}
303-
304-
if (nanosleep(&sleep_time, NULL) == 0) {
305-
break;
306-
}
307-
308-
if (errno != EINTR) {
309-
fprintf(stderr, "nanosleep failed\n");
310-
break;
311-
}
312-
313-
if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
314-
fprintf(stderr, "clock_gettime failed\n");
315-
break;
316-
}
317-
}
318-
319-
next_tick = timespec_add_us(next_tick, PERIOD_US);
320-
}
236+
rx_coop_exec_init(&ce);
237+
rx_coop_exec_add(&ce, &runtime.runtime);
238+
rx_coop_exec_run(&ce); /* never returns */
321239

322-
rx_fsm_runtime_free(&runtime);
323240
return 0;
324241
}

0 commit comments

Comments
 (0)