-
Notifications
You must be signed in to change notification settings - Fork 0
/
Coro.h
161 lines (114 loc) · 2.89 KB
/
Coro.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
154
155
156
157
158
159
160
161
#ifndef CORO_CORO_H
#define CORO_CORO_H
#include <functional>
//#define _XOPEN_SOURCE 600
#include <ucontext.h>
#include <unordered_map>
#include <memory>
#include <assert.h>
#include <list>
#include <queue>
enum Coro_Satus {
CORO_DEATH,
CORO_READY,
CORO_RUNNING,
CORO_SUSPEND
};
typedef std::function<void()> coroutine_func;
#define MAX_STACK_SIZE (1024 * 1024)
#define DEAFULT_NUM 16
#define CO_NUM_LIMIT 256
class coroutine {
public:
coroutine(const coroutine_func &f, int id);
~coroutine();
Coro_Satus &status() { return status_; }
void set_status(Coro_Satus s);
ucontext_t &ctx() { return ctx_; }
char *stack() { return stack_; }
int &id() { return id_; }
void run();
private:
int id_;
ucontext_t ctx_;//context
coroutine_func func_;//running function
Coro_Satus status_;//running status
// char stack[MAX_STACK_SIZE];// running stack
char *stack_;
};
typedef std::shared_ptr<coroutine> Coroutine_ptr;
class Coro {
public:
// Coro(int ss = MAX_STACK_SIZE);
explicit Coro(int ss = MAX_STACK_SIZE, int cap = DEAFULT_NUM);
~Coro();
void resume(int id);
void yield();
int create(const coroutine_func &f);
int &co_num();
Coroutine_ptr get_co(int id);
Coro_Satus get_co_status(int id);
int curr() { return curr_; };
private:
ucontext_t mctx;//main context
// coroutine *running_co;//running coroutine
// std::set<coroutine *> coroutines;// store coroutines
int curr_;//id of running coroutine
int nco;//num of running coroutine
int cap; //cap of Coro
// std::vector<coroutine *> coroutines;
std::unordered_map<int, Coroutine_ptr> coroutines;
int stack_size;
static void excute_fun(uint32_t low32, uint32_t hi32);
};
template<typename Type>
class Channel {
public:
explicit Channel(std::shared_ptr<Coro> s, int id = -1) : taker_(id), schedule(std::move(s)) {
}
void consumer(int id) {
taker_ = id;
}
void push(const Type &v);
Type pop();
void clear() {
clear_(queue_);
}
size_t message_num() {
return queue_.size();
}
bool is_empty() {
return queue_.empty();
}
private:
// std::list<Type> list_;
std::queue<Type> queue_;
int taker_;
std::shared_ptr<Coro> schedule;
void clear_(std::queue<Type> &q){
std::queue<Type> empty;
swap(q,empty);
}
};
template<typename Type>
Type Channel<Type>::pop() {
if (taker_ == -1 ) {
taker_ = schedule->curr();
}
auto co = schedule->get_co(taker_);
//block
while (queue_.empty()) {
schedule->yield();
}
Type v = queue_.front();
queue_.pop();
return std::move(v);
}
template<typename Type>
void Channel<Type>::push(const Type &v) {
queue_.push(v);
if (taker_ != -1 && taker_ != schedule->curr()) {
schedule->resume(taker_);
}
}
#endif //CORO_CORO_H