Mirai's Miscellaneous Misadventures

M23 / core / coroutines.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
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}