1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/* libcr_ipc/tests/test_chan.c - Tests for <libcr_ipc/chan.h>
*
* Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libcr/coroutine.h>
#include <libcr_ipc/chan.h>
#include "test.h"
CR_CHAN_DECLARE(intchan, int);
/* test 1 *********************************************************************/
COROUTINE test1_producer_cr(void *_ch) {
intchan_t *ch = _ch;
cr_begin();
cr_chan_send(ch, 1);
while (!cr_chan_can_send(ch))
cr_yield();
cr_chan_send(ch, 2);
cr_end();
}
COROUTINE test1_consumer_cr(void *_ch) {
int x;
intchan_t *ch = _ch;
cr_begin();
x = cr_chan_recv(ch);
test_assert(x == 1);
x = cr_chan_recv(ch);
test_assert(x == 2);
cr_end();
}
/* test 2 *********************************************************************/
intchan_t test2_ch[10] = {};
intchan_t test2_fch = {};
COROUTINE test2_consumer_cr(void *) {
cr_begin();
struct cr_select_arg args[11];
bool chdone[10] = {};
int arg2ch[10];
for (;;) {
int ret_ch;
int i_arg = 0;
for (int i_ch = 0; i_ch < 10; i_ch++) {
if (!chdone[i_ch]) {
args[i_arg] = CR_SELECT_RECV(&test2_ch[i_ch], &ret_ch);
arg2ch[i_arg] = i_ch;
i_arg++;
}
}
if (!i_arg)
break;
args[i_arg] = CR_SELECT_DEFAULT; /* check that default doesn't trigger */
test_assert(i_arg <= 10);
int ret_arg = cr_select_v(i_arg+1, args);
test_assert(ret_arg < i_arg);
test_assert(arg2ch[ret_arg] == ret_ch);
chdone[ret_ch] = true;
}
int ret_ch, ret_arg;
args[0] = CR_SELECT_RECV(&test2_ch[0], &ret_ch);
args[1] = CR_SELECT_DEFAULT;
ret_arg = cr_select_v(2, args);
test_assert(ret_arg == 1);
int send = 567;
args[0] = CR_SELECT_SEND(&test2_fch, &send);
args[1] = CR_SELECT_DEFAULT;
ret_arg = cr_select_v(2, args);
test_assert(ret_arg == 0);
send = 890;
ret_arg = cr_select_l(CR_SELECT_SEND(&test2_fch, &send),
CR_SELECT_DEFAULT);
test_assert(ret_arg == 1);
cr_end();
}
COROUTINE test2_producer_cr(void *_n) {
int n = *(int *)_n;
cr_begin();
cr_chan_send(&test2_ch[n], n);
cr_end();
}
COROUTINE test2_final_cr(void *) {
cr_begin();
int ret = cr_chan_recv(&test2_fch);
printf("ret=%d\n", ret);
test_assert(ret == 567);
cr_end();
}
/******************************************************************************/
int main() {
printf("== test 1 =========================================\n");
intchan_t ch = {};
coroutine_add("producer", test1_producer_cr, &ch);
coroutine_add("consumer", test1_consumer_cr, &ch);
coroutine_main();
printf("== test 2 =========================================\n");
for (int i = 0; i < 10; i++)
coroutine_add("producer", test2_producer_cr, &i);
coroutine_add("consumer", test2_consumer_cr, NULL);
coroutine_add("final", test2_final_cr, NULL);
coroutine_main();
return 0;
}
|