Subastra
Loading...
Searching...
No Matches
scheduler.h
Go to the documentation of this file.
1#ifndef __H__SYSTEMS_SCHEDULER__
2#define __H__SYSTEMS_SCHEDULER__
3
4#include <stdio.h>
5
6#include "../list.h"
7#include "../names.h"
8#include "require.h"
9
13
18
29
31 allocator_t persistent_allocator,
32 allocator_t temporary_allocator) {
33 scheduler_t ret;
34
35 ret.temporary_allocator = temporary_allocator;
36 ret.persistent_allocator = persistent_allocator;
37
38 ret.strategy = strategy;
39
40 ret.scheduler_systems = allocator_alloc_ty(list_t, ret.persistent_allocator,
42
43 for (int i = 0; i < SYSTEM_PHASE_count; i++) {
46 }
47
48 return ret;
49}
50
51static void scheduler_add_system(scheduler_t *scheduler, system_req_t req,
52 system_runner_f runner) {
53 scheduler_system_t system;
54 system.runner = runner;
55 system.reqs = req;
56
57 list_push_var(&scheduler->scheduler_systems[req.phase], system);
58}
59
60#define scheduler_declare_system_with_custom_runner( \
61 scheduler, mut, cons, system_name, runner_f, deps_on, dependency_count, \
62 ...) \
63 name_t runner_f##_name = as_name(#system_name); \
64 do { \
65 system_req_t __system_req = __VA_ARGS__; \
66 __system_req.name = runner_f##_name; \
67 __system_req.depends_on = deps_on; \
68 __system_req.depends_on_count = dependency_count; \
69 system_req_entity_kinds_const(&__system_req, cons); \
70 system_req_entity_kinds_mut(&__system_req, mut); \
71 scheduler_add_system(scheduler, __system_req, runner_f); \
72 } while (0)
73
79#define scheduler_declare_system(scheduler, mut, cons, system_name, \
80 depends_on, dependency_count, ...) \
81 scheduler_declare_system_with_custom_runner( \
82 scheduler, mut, cons, system_name, system_##system_name, depends_on, \
83 dependency_count, __VA_ARGS__)
84
86 scheduler_t *scheduler, system_requirements_declaration_t *declaration,
87 void *system_specific_data) {
88 name_t name = as_name(declaration->name);
89
90 name_t *deps = 0;
91 if (declaration->dependencies) {
92 deps = allocator_alloc_ty(name_t, scheduler->persistent_allocator,
93 declaration->dependency_count);
94 for (sz i = 0; i < declaration->dependency_count; i++)
95 deps[i] = as_name(declaration->dependencies[i]);
96 }
97
98 system_req_t reqs;
99 reqs.depends_on = deps;
100 reqs.depends_on_count = declaration->dependency_count;
101 reqs.name = name;
102 reqs.phase = declaration->phase;
103 reqs.pin_to_main = declaration->pin_to_main;
104 reqs.resources = declaration->resources;
105 reqs._entity_kinds_const = declaration->entities_const;
106 reqs._entity_kinds_mut = declaration->entities_mut;
107
109 (system_specific_data == 0));
110
111 system_runner_f runner = declaration->runner;
112 scheduler_add_system(scheduler, reqs, runner);
113}
114
115static void
120
121static void scheduler_dump_dependency_graph(scheduler_t *scheduler, FILE *out) {
122 sz capacity = 0;
123 for (int phase_idx = 0; phase_idx < (int)SYSTEM_PHASE_count; phase_idx++)
124 capacity += scheduler->scheduler_systems[phase_idx].size;
125
127 list_t execution_order;
128 list_init_ty_with_capacity(name_t, &execution_order, alloc, capacity);
129
130 fprintf(out, "digraph G {\n\trankdir=\"TB\";\n");
131
132 for (int phase_idx = 0; phase_idx < (int)SYSTEM_PHASE_count; phase_idx++) {
133 list_t *sys_list = &scheduler->scheduler_systems[phase_idx];
134
135 if (sys_list->size == 0)
136 continue;
137
138 const char *sys_name_str = system_phase_to_str((system_phase_t)phase_idx);
139
140 fprintf(out,
141 "\tsubgraph cluster_%d {\n\t\tlabel = \"%s\";\n\t\tstyle = "
142 "filled;\n\t\tcolor = lightgrey;\n",
143 phase_idx, sys_name_str);
144
145 for (sz i = 0; i < sys_list->size; i++) {
146 scheduler_system_t *sys =
148
149 name_t name = sys->reqs.name;
150 const char *name_str = name_as_str(name);
151
152 fprintf(out, "\t\t%ld [label=\"%s #%ld\"];\n", name, name_str, i);
153
154 for (sz j = 0; j < sys->reqs.depends_on_count; j++) {
155 name_t dependency = sys->reqs.depends_on[j];
156 fprintf(out, "\t\t%ld -> %ld;\n", dependency, name);
157 }
158
159 list_push_var(&execution_order, name);
160 }
161
162 fprintf(out, "\t}\n");
163 }
164
165 fprintf(out, "\tstart [color = blue, shape = Mdiamond];\n");
166 fprintf(out, "\tend [color = blue, shape = Mdiamond];\n");
167 fprintf(out, "\t{ rank=\"source\"; \"start\";}\n");
168 fprintf(out, "\t{ rank=\"sink\"; \"end\";}\n");
169
170 fprintf(out, "\tstart -> %ld [color = blue];\n",
171 list_get_ty(name_t, &execution_order, 0));
172 for (sz i = 0; i < execution_order.size - 1; i++) {
173 name_t n1 = list_get_ty(name_t, &execution_order, i);
174 name_t n2 = list_get_ty(name_t, &execution_order, i + 1);
175
176 fprintf(out, "\t%ld -> %ld [color = blue];\n", n1, n2);
177 }
178
179 fprintf(out, "\t%ld -> end [color = blue];\n",
180 list_get_ty(name_t, &execution_order, execution_order.size - 1));
181
182 fprintf(out, "}\n");
183}
184
186 list_t *scheduler_system_list) {
187 ASSERT__(scheduler_system_list->_entry == sizeof(scheduler_system_t));
188
189 map_t coordinate_compression_forward;
190 map_init_ty(sz, &coordinate_compression_forward, alloc);
191 map_t coordinate_compression_reverse;
192 map_init_ty(sz, &coordinate_compression_reverse, alloc);
193
194 for (sz i = 0; i < scheduler_system_list->size; i++) {
195 name_t n = list_get_ty(name_t, scheduler_system_list, i);
196 if (!map_get(&coordinate_compression_forward, n)) {
197 map_insert_ty(sz, &coordinate_compression_forward, n,
198 &coordinate_compression_forward.size);
199 }
200 }
201
202 ASSERT__(coordinate_compression_forward.size == scheduler_system_list->size);
203 ASSERT__(coordinate_compression_reverse.size == scheduler_system_list->size);
204
205 map_cleanup(&coordinate_compression_forward);
206 map_cleanup(&coordinate_compression_reverse);
207}
208
210 system_payload_t payload) {
211 scheduler->parent_payload = payload;
212}
213
216static void scheduler_tick(scheduler_t *scheduler, double delta_time) {
217 scheduler->parent_payload.delta_time = delta_time;
218}
219
220static void scheduler_begin_running(scheduler_t *scheduler) {
221 for (int phase_idx = 0; phase_idx < (int)SYSTEM_PHASE_count; phase_idx++) {
222 list_t *sys_list = &scheduler->scheduler_systems[phase_idx];
223
224 for (sz i = 0; i < sys_list->size; i++) {
225 scheduler_system_t *system =
227
228 system_payload_t payload =
229 system_payload_new_inherit(system->reqs, &scheduler->parent_payload);
230 system->runner(payload, scheduler->temporary_allocator);
231 }
232 }
233}
234
235static void scheduler_end_running(scheduler_t *scheduler) {}
236
237#endif
#define ASSERT__(expr)
Definition defs.h:21
size_t sz
Definition defs.h:51
#define list_get_ty_ptr(ty, ls, idx)
Definition list.h:128
#define list_init_ty(ty, ls, alloc)
Definition list.h:36
#define list_get_ty(ty, ls, idx)
Definition list.h:130
#define list_init_ty_with_capacity(ty, ls, alloc, capacity)
Definition list.h:38
#define list_push_var(ls, var)
Definition list.h:83
#define map_insert_ty(ty, map, key, data)
Definition map.h:196
static allocator_t allocator_new_stack_alloc()
Definition memory.h:113
static name_t as_name(const char *str)
Definition names.h:33
static const char * name_as_str(name_t name)
Definition names.h:51
u64 name_t
Definition names.h:14
static system_payload_t system_payload_new_inherit(system_req_t requirements, system_payload_t *parent)
Copy the parameters specified in the requirements into a new payload.
Definition require.h:127
void(* system_runner_f)(system_payload_t payload, allocator_t temporary_allocator)
Definition require.h:64
static const char * system_phase_to_str(system_phase_t phase)
Definition require.h:21
@ SYSTEM_RESOURCE_MASK_SYSTEM_SPECIFIC_DATA
Definition require.h:71
system_phase_t
Definition require.h:10
@ SYSTEM_PHASE_count
Definition require.h:18
static void scheduler_dump_dependency_graph(scheduler_t *scheduler, FILE *out)
Definition scheduler.h:121
static void scheduler_add_system(scheduler_t *scheduler, system_req_t req, system_runner_f runner)
Definition scheduler.h:51
static void scheduler_set_parent_payload(scheduler_t *scheduler, system_payload_t payload)
Definition scheduler.h:209
static void scheduler_add_system_declared(scheduler_t *scheduler, system_requirements_declaration_t *declaration)
Definition scheduler.h:116
scheduler_strategy_t
Definition scheduler.h:10
@ SCHEDULER_STRATEGY_RANDOM
Definition scheduler.h:11
static void scheduler_tick(scheduler_t *scheduler, double delta_time)
Definition scheduler.h:216
static void scheduler_end_running(scheduler_t *scheduler)
Definition scheduler.h:235
static scheduler_t scheduler_new(scheduler_strategy_t strategy, allocator_t persistent_allocator, allocator_t temporary_allocator)
Definition scheduler.h:30
static void scheduler_begin_running(scheduler_t *scheduler)
Definition scheduler.h:220
static void scheduler__topological_sort(allocator_t alloc, list_t *scheduler_system_list)
Definition scheduler.h:185
static void scheduler_add_system_declared_specific_data(scheduler_t *scheduler, system_requirements_declaration_t *declaration, void *system_specific_data)
Definition scheduler.h:85
A generic allocator type passed by value. Contains a fallback allocator and a set of function pointer...
Definition memory.h:30
Definition list.h:13
sz size
Definition list.h:17
sz _entry
Definition list.h:15
Definition map.h:28
sz size
The amount of elements currently in the map.
Definition map.h:38
Definition scheduler.h:14
system_runner_f runner
Definition scheduler.h:16
system_req_t reqs
Definition scheduler.h:15
Definition scheduler.h:19
list_t * scheduler_systems
Definition scheduler.h:27
allocator_t temporary_allocator
Allocator for all data that lives for one frame.
Definition scheduler.h:23
system_payload_t parent_payload
Definition scheduler.h:26
scheduler_strategy_t strategy
Definition scheduler.h:24
allocator_t persistent_allocator
Allocator for the data that persist over the scheduler's lifetime.
Definition scheduler.h:21
Definition require.h:51
double delta_time
Definition require.h:60
Definition require.h:74
system_resource_mask_t resources
Definition require.h:83
name_t name
Definition require.h:76
entity_kind_mask_t _entity_kinds_const
Definition require.h:78
system_phase_t phase
Definition require.h:75
u32 depends_on_count
Definition require.h:81
entity_kind_mask_t _entity_kinds_mut
Definition require.h:77
name_t * depends_on
Definition require.h:80
bool pin_to_main
Definition require.h:86
Definition require.h:89
system_resource_mask_t resources
Definition require.h:99
entity_kind_mask_t entities_mut
Definition require.h:94
system_phase_t phase
Definition require.h:91
const char ** dependencies
Definition require.h:96
entity_kind_mask_t entities_const
Definition require.h:93
const char * name
Definition require.h:90
system_runner_f runner
Definition require.h:102
u32 dependency_count
Definition require.h:97
bool pin_to_main
Definition require.h:100