Mirai's Miscellaneous Misadventures
M25 / core / coroutines.c
1
2
3
4#include <mimimi/coroutines.h>
5#include <mimimi/coroutine-providers.h>
6#include <mimimi/compound-behaviors.h>
7#include <mimimi/behaviors.h>
8#include <mimimi/allocators.h>
9
10struct mimimi_coroutine
11{
12 struct mimimi_allocator *allocator;
13 struct mimimi_behavior *behavior;
14 struct mimimi_behavior *compound0;
15 struct mimimi_behavior *compound;
16 struct mimimi_behavior *result;
17 void (*start)(struct mimimi_behavior *behavior, struct mimimi_behavior *compound, void *data);
18 void *data;
19 char finished;
20};
21
22static void mimimi_coroutine_start(struct mimimi_behavior *behavior, void *data)
23{
24 struct mimimi_coroutine *coroutine = data;
25 (*coroutine->start)(behavior, coroutine->compound, coroutine->data);
26}
27
28static void mimimi_coroutine_finish_behavior(void *data)
29{
30 struct mimimi_coroutine *coroutine = data;
31 mimimi_compound_remove(coroutine->compound0, coroutine->result);
32 (*coroutine->behavior->finish)(coroutine->behavior->data);
33 (*coroutine->compound->finish)(coroutine->compound->data);
34 (*coroutine->allocator->deallocate)(coroutine->result);
35 (*coroutine->allocator->deallocate)(coroutine);
36}
37
38static void mimimi_coroutine_finish(void *data)
39{
40 struct mimimi_coroutine *coroutine = data;
41 coroutine->finished = 1;
42 if (mimimi_compound_empty(coroutine->compound) != 0)
43 mimimi_coroutine_finish_behavior(data);
44}
45
46static void mimimi_coroutine_behave(void *data)
47{
48 struct mimimi_coroutine *coroutine = data;
49 if (coroutine->finished == 0)
50 (*coroutine->behavior->behave)(coroutine->behavior->data);
51 (*coroutine->compound->behave)(coroutine->compound->data);
52
53 if (coroutine->finished != 0)
54 if (mimimi_compound_empty(coroutine->compound) != 0)
55 mimimi_coroutine_finish_behavior(data);
56}
57
58void mimimi_coroutine(struct mimimi_coroutine_provider *coroutines, struct mimimi_behavior *compound, void (*start)(struct mimimi_behavior *behavior, struct mimimi_behavior *compound, void *data), void *data, struct mimimi_allocator *allocator)
59{
60 struct mimimi_coroutine *coroutine = (*allocator->allocate)(sizeof *coroutine);
61 coroutine->start = start;
62 coroutine->data = data;
63 coroutine->allocator = allocator;
64 coroutine->compound0 = compound;
65 coroutine->compound = mimimi_compound_behavior(allocator);
66 coroutine->finished = 0;
67
68 struct mimimi_behavior *behavior = (*coroutines->create)(&mimimi_coroutine_start, &mimimi_coroutine_finish, coroutine, coroutines->data);
69 coroutine->behavior = behavior;
70
71 struct mimimi_behavior *result = (allocator->allocate)(sizeof *result);
72 result->behave = &mimimi_coroutine_behave;
73 result->finish = &mimimi_coroutine_finish_behavior;
74 result->data = coroutine;
75 coroutine->result = result;
76
77 mimimi_compound(compound, result);
78}