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
|
/* libcr_ipc/tests/test_select.c - Tests for <libcr_ipc/select.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/select.h>
#include "test.h"
CR_CHAN_DECLARE(intchan, int);
intchan_t ch[10] = {0};
intchan_t fch = {0};
COROUTINE cr_consumer(void *) {
cr_begin();
struct cr_select_arg args[11];
bool chdone[10] = {0};
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(&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(&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(&fch, &send);
args[1] = CR_SELECT_DEFAULT;
ret_arg = cr_select_v(2, args);
test_assert(ret_arg == 0);
send = 890;
args[0] = CR_SELECT_SEND(&fch, &send);
args[1] = CR_SELECT_DEFAULT;
ret_arg = cr_select_v(2, args);
test_assert(ret_arg == 1);
cr_end();
}
COROUTINE cr_producer(void *_n) {
int n = *(int *)_n;
cr_begin();
intchan_send(&ch[n], n);
cr_end();
}
COROUTINE cr_final(void *) {
cr_begin();
int ret = intchan_recv(&fch);
printf("ret=%d\n", ret);
test_assert(ret == 567);
cr_end();
}
int main() {
for (int i = 0; i < 10; i++)
coroutine_add("producer", cr_producer, &i);
coroutine_add("consumer", cr_consumer, NULL);
coroutine_add("final", cr_final, NULL);
coroutine_main();
return 0;
}
|