-
Notifications
You must be signed in to change notification settings - Fork 0
/
Scheduler.h
153 lines (120 loc) · 3.39 KB
/
Scheduler.h
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <thread>
#include <coroutine>
#include <vector>
#include <variant>
#include <atomic>
#include <list>
#include <assert.h>
#include <iostream>
#pragma once
// FIXME: call delete() for std::coroutine_handle
// TODO: add custom new() for promise for allocing the coro-frame
template<typename T> class AtomicQueue
{};
enum class FunctionalJobExecutionResult {
FinalCompleted,
AwaitNewJob,
};
enum class WorkplaceJobExecutionResult {
FinalCompleted, // Cleanup job, Run job awaiting the result, or new job.
YieldCompleted, // Yielded, Run job awaiting the result, or new job.
AwaitNewJob, // Return job to run, add job to await list. Run next job.
};
struct JobCompleted {};
struct JobYielded {};
class Executor
{
public:
std::list<std::coroutine_handle<>> coList{};
template<typename T> void resumeJob(T& t);
};
int debugCounter = 0;
template<typename T> class WorkplaceCoroutineJob
{
int _debugID = debugCounter++;
friend class Executor;
public:
struct JobCoroutine {
static std::suspend_always initial_suspend() { return {}; }
static std::suspend_always final_suspend() noexcept { return {}; }
static void unhandled_exception(){};
Executor* upper = nullptr;
void return_value(T i) { returnValue = i; }
// Get a return object for the creator of a job
WorkplaceCoroutineJob<T> get_return_object() {
return WorkplaceCoroutineJob{*this};
}
bool hasValue() const { return returnValue.has_value(); }
T getValue() { return returnValue.value(); }
std::optional<T> returnValue{};
template<typename U>
auto await_transform(WorkplaceCoroutineJob<U> job) {
upper->coList.push_front(job.getCoroutineHandle());
job.getPromise().upper = upper;
return AwaitedJobToDo<U>(job.getPromise());
}
};
private:
JobCoroutine& coroutine;
public:
using promise_type = JobCoroutine;
using OneToOneTaskStrongHandle = std::coroutine_handle<JobCoroutine>;
WorkplaceCoroutineJob(JobCoroutine& h): coroutine(h) {}
template<typename U> struct AwaitedJobToDo {
WorkplaceCoroutineJob<U>::JobCoroutine& c;
AwaitedJobToDo(WorkplaceCoroutineJob<U>::JobCoroutine& newJob):
c(newJob) {}
void await_ready() {}
U await_resume() { return c.getValue(); }
bool await_suspend(auto t) { return true; }
};
std::unique_ptr<Executor> executor;
JobCoroutine& getPromise() { return coroutine; }
bool isDone() const { return coroutine.hasValue(); }
OneToOneTaskStrongHandle getCoroutineHandle() const {
return OneToOneTaskStrongHandle::from_promise(coroutine);
}
T getValue() { return coroutine.getValue(); }
};
template<typename T> inline void Executor::resumeJob(T& t) {
if (!t.executor)
{
t.executor = std::unique_ptr<Executor>(new Executor{});
t.coroutine.upper = this;
}
if (!coList.empty())
{
auto c = coList.front();
c.resume();
if (c.done()) coList.pop_front();
} else
t.getCoroutineHandle().resume();
}
WorkplaceCoroutineJob<int> makeOne();
WorkplaceCoroutineJob<float> makeOneF() { co_return 1.f; }
WorkplaceCoroutineJob<int> makeOne() { co_return(int) co_await makeOneF(); }
WorkplaceCoroutineJob<double> doStuff() {
co_return(double) co_await makeOne();
}
void mainLoop() {
auto start = doStuff();
auto executor = Executor();
int i = 0;
while (!start.isDone())
{
executor.resumeJob(start);
i++;
}
double r = start.getValue();
i++;
}
class Worker: std::thread
{
public:
};
class Scheduler
{
public:
Scheduler();
std::vector<Worker> workers;
};