-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcoroutine_stuff.h
66 lines (53 loc) · 1.44 KB
/
coroutine_stuff.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
#pragma once
#include <iostream>
#include <array>
#include <functional>
#include <vector>
#include <boost/context/all.hpp>
namespace NContext = boost::context;
class TCoroutine;
__thread TCoroutine* ActiveCoroutine = nullptr;
class TCoroutine {
friend void Yield();
typedef std::function<void(TCoroutine*)> TFunction;
TFunction Function;
bool Started;
bool Running;
std::array<uint8_t, 64 * 1024> Stack;
NContext::fcontext_t* FunctionContext;
NContext::fcontext_t MainContext;
void Yield() {
NContext::jump_fcontext(FunctionContext, &MainContext, 0);
}
static void Wrapper(intptr_t pointer) {
TCoroutine* coroutine = reinterpret_cast<TCoroutine*>(pointer);
coroutine->Started = true;
coroutine->Function(coroutine);
coroutine->Started = false;
coroutine->Yield();
}
public:
explicit TCoroutine(TFunction function)
: Function(function)
, Started(false)
, Running(false)
, FunctionContext(NContext::make_fcontext(Stack.data() + Stack.size(), Stack.size(), Wrapper))
{}
void Go() {
TCoroutine* previous = this;
std::swap(ActiveCoroutine, previous);
Running = true;
NContext::jump_fcontext(&MainContext, FunctionContext, reinterpret_cast<intptr_t>(this));
Running = false;
std::swap(ActiveCoroutine, previous);
}
bool IsStarted() const {
return Started;
}
bool IsRunning() const {
return Running;
}
};
void Yield() {
ActiveCoroutine->Yield();
}