Ruby 4.1.0dev (2026-09-27 revision f6ff9e7d02e46360f8930b280a3dd921cccbda29)
Context.h
1/*
2 * This file is part of the "Coroutine" project and released under the MIT License.
3 *
4 * Created by Samuel Williams on 24/6/2021.
5 * Copyright, 2021, by Samuel Williams.
6*/
7
8#pragma once
9
10#include <assert.h>
11#include <stddef.h>
12#include <pthread.h>
13
14#define COROUTINE void
15
16#define COROUTINE_PTHREAD_CONTEXT
17
18#ifdef HAVE_STDINT_H
19#include <stdint.h>
20#if INTPTR_MAX <= INT32_MAX
21#define COROUTINE_LIMITED_ADDRESS_SPACE
22#endif
23#endif
24
26
27typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
28
30{
31 /* NULL for a main context; otherwise the worker pthread entry point. */
32 coroutine_start start;
33 void *argument;
34
35 void *stack;
36 size_t size;
37
38 /* The current caller for a main context, or the context's worker pthread. */
39 pthread_t id;
40
41 /* Whether the lazily created worker pthread must be cancelled and joined.
42 * This remains false for a main context, whose id is the caller's pthread. */
43 int thread_created;
44
45 /* Serializes updates to suspended and from, and is paired with schedule. */
46 pthread_mutex_t guard;
47
48 /* Wakes this context when another context transfers control to it. */
49 pthread_cond_t schedule;
50
51 /* Whether this context is inactive and can be resumed. This is also the
52 * predicate protected by guard and checked when waiting on schedule. */
53 int suspended;
54
55 /* Whether guard and schedule have been initialized and remain valid. */
56 int initialized;
57
58 /* The context that most recently transferred control to this context. */
59 struct coroutine_context * from;
60};
61
62void coroutine_initialize_main(struct coroutine_context * context);
63
64void coroutine_initialize(
65 struct coroutine_context *context,
66 coroutine_start start,
67 void *stack,
68 size_t size
69);
70
71struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
72
73void coroutine_destroy(struct coroutine_context * context);