Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
05_parallel.c
Go to the documentation of this file.
1/* -*- C -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <[email protected]>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19// Example 05 -- many fibers across many worker threads (M:N).
20//
21// The same scheduler runs on more than one OS thread by passing a worker count
22// greater than one to `srn_sched_run`. The fibers are distributed across the
23// workers, which steal work from one another to stay busy, so the fibers run in
24// parallel rather than merely interleaved. The run returns once every worker is
25// idle on an empty queue.
26//
27// Because the fibers run on different threads at the same time, any state they
28// share has to be synchronised. This example keeps it simple with a single
29// atomic counter that every fiber increments once. After the run the total
30// equals the fiber count, with no lost updates.
31
32#include <stdatomic.h>
33#include <stdio.h>
34
35#include <serene/runtime.h>
36
37#define FIBER_COUNT 1000
38#define WORKER_COUNT 4
39
40static atomic_int total;
41
43 (void)ctx;
44 (void)arg;
45 // The one piece of shared state. An atomic add is safe from any worker.
46 atomic_fetch_add(&total, 1);
47 return nullptr;
48}
49
50int main(void) {
51 SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, nullptr);
52 srn_context_t *ctx = srn_context_make(engine);
53
54 atomic_store(&total, 0);
55 for (int i = 0; i < FIBER_COUNT; i++) {
56 (void)srn_fiber_spawn(ctx, increment, nullptr);
57 }
58
59 printf("running %d fibers across %d workers\n", FIBER_COUNT, WORKER_COUNT);
61
62 int counted = atomic_load(&total);
63 printf(
64 "counted %d (expected %d): %s\n", counted, FIBER_COUNT,
65 counted == FIBER_COUNT ? "all fibers ran" : "lost an update"
66 );
67
70 return 0;
71}
#define FIBER_COUNT
Definition 05_parallel.c:37
static srn_fiber_result_t increment(srn_context_t *ctx, void *arg)
Definition 05_parallel.c:42
int main(void)
Definition 05_parallel.c:50
static atomic_int total
Definition 05_parallel.c:40
#define WORKER_COUNT
Definition 05_parallel.c:38
srn_context_t * srn_context_make(srn_engine_t *engine)
Make an empty context, by allocating a new memory block.
Definition context.c:39
int srn_context_release(srn_context_t *ctx)
Definition context.c:64
srn_fiber_t * srn_fiber_spawn(srn_context_t *ctx, srn_fiber_entry_t entry, void *arg)
Make and schedule a fiber with every default, the engine's scheduler, the configured stack size,...
Definition fiber.c:247
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
Definition fiber.h:157
#define SERENE_RUNTIME_SHUTDOWN(engine)
Tear down what SERENE_RUNTIME_INIT brought up, in reverse order, the engine (reactor,...
Definition runtime.h:58
#define SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, config)
SERENE_RUNTIME_INIT plus a sched variable bound to the engine's scheduler, which every run and fiber ...
Definition runtime.h:46
void srn_sched_run(srn_scheduler_t *sched, size_t nworkers)
Run the scheduler with nworkers os threads draining it, returning once the pool goes quiescent (every...
Definition scheduler.c:843