20 #ifndef STDEX_COROUTINE_H_ 21 #define STDEX_COROUTINE_H_ 24 #define STACK_LIMIT (1024*1024) 44 #if defined(__APPLE__) && defined(__MACH__) 67 std::function<void()> func;
71 Routine(std::function<
void()> f)
86 std::vector<Routine *> routines;
87 std::list<routine_t> indexes;
96 fiber = ConvertThreadToFiber(
nullptr);
101 for (
auto &routine : routines)
108 inline routine_t
create(std::function<
void()> f)
112 if (ordinator.indexes.empty())
114 ordinator.routines.push_back(routine);
115 return ordinator.routines.size();
119 routine_t
id = ordinator.indexes.front();
120 ordinator.indexes.pop_front();
121 assert(ordinator.routines[
id-1] ==
nullptr);
122 ordinator.routines[
id-1] = routine;
127 inline void destroy(routine_t
id)
129 Routine *routine = ordinator.routines[
id-1];
130 assert(routine !=
nullptr);
133 ordinator.routines[
id-1] =
nullptr;
134 ordinator.indexes.push_back(
id);
137 inline void __stdcall
entry(LPVOID lpParameter)
139 routine_t
id = ordinator.current;
140 Routine *routine = ordinator.routines[
id-1];
141 assert(routine !=
nullptr);
146 ordinator.current = 0;
148 SwitchToFiber(ordinator.fiber);
153 assert(ordinator.current == 0);
155 Routine *routine = ordinator.routines[
id-1];
156 if (routine ==
nullptr)
162 if (routine->fiber ==
nullptr)
164 routine->fiber = CreateFiber(ordinator.stack_size,
entry, 0);
165 ordinator.current = id;
166 SwitchToFiber(routine->fiber);
170 ordinator.current = id;
171 SwitchToFiber(routine->fiber);
179 routine_t
id = ordinator.current;
180 Routine *routine = ordinator.routines[
id-1];
181 assert(routine !=
nullptr);
183 ordinator.current = 0;
184 SwitchToFiber(ordinator.fiber);
189 return ordinator.current;
193 template<
typename Function>
194 inline typename std::result_of<Function()>::type
195 await(Function &&func)
197 auto future = std::async(std::launch::async, func);
198 std::future_status status = future.wait_for(std::chrono::milliseconds(0));
200 while (status == std::future_status::timeout)
202 if (ordinator.current != 0)
205 status = future.wait_for(std::chrono::milliseconds(0));
212 template<
typename Function>
213 inline std::result_of_t<std::decay_t<Function>()>
214 await(Function &&func)
216 auto future = std::async(std::launch::async, func);
217 std::future_status status = future.wait_for(std::chrono::milliseconds(0));
219 while (status == std::future_status::timeout)
221 if (ordinator.current != 0)
224 status = future.wait_for(std::chrono::milliseconds(0));
268 for (
auto &routine : routines)
275 inline routine_t
create(std::function<
void()> f)
279 if (ordinator.indexes.empty())
281 ordinator.routines.push_back(routine);
282 return ordinator.routines.size();
286 routine_t
id = ordinator.indexes.front();
287 ordinator.indexes.pop_front();
288 assert(ordinator.routines[
id-1] ==
nullptr);
289 ordinator.routines[
id-1] = routine;
296 Routine *routine = ordinator.routines[
id-1];
297 assert(routine !=
nullptr);
300 ordinator.routines[
id-1] =
nullptr;
305 routine_t
id = ordinator.current;
306 Routine *routine = ordinator.routines[
id-1];
310 ordinator.current = 0;
311 ordinator.indexes.push_back(
id);
316 assert(ordinator.current == 0);
318 Routine *routine = ordinator.routines[
id-1];
319 if (routine ==
nullptr)
325 if (routine->
stack ==
nullptr)
330 getcontext(&routine->
ctx);
335 routine->
stack =
new char[ordinator.stack_size];
336 routine->
ctx.uc_stack.ss_sp = routine->
stack;
337 routine->
ctx.uc_stack.ss_size = ordinator.stack_size;
338 routine->
ctx.uc_link = &ordinator.ctx;
339 ordinator.current = id;
344 makecontext(&routine->
ctx, reinterpret_cast<void (*)(
void)>(
entry), 0);
348 swapcontext(&ordinator.ctx, &routine->
ctx);
352 ordinator.current = id;
353 swapcontext(&ordinator.ctx, &routine->
ctx);
361 routine_t
id = ordinator.current;
362 Routine *routine = ordinator.routines[
id-1];
363 assert(routine !=
nullptr);
365 char *stack_top = routine->
stack + ordinator.stack_size;
366 char stack_bottom = 0;
367 assert(
size_t(stack_top - &stack_bottom) <= ordinator.stack_size);
369 ordinator.current = 0;
370 swapcontext(&routine->
ctx , &ordinator.ctx);
375 return ordinator.current;
378 template<
typename Function>
379 inline typename std::result_of<Function()>::type
382 auto future = std::async(std::launch::async, func);
383 std::future_status status = future.wait_for(std::chrono::milliseconds(0));
385 while (status == std::future_status::timeout)
387 if (ordinator.current != 0)
390 status = future.wait_for(std::chrono::milliseconds(0));
397 template<
typename Type>
418 _list.push_back(obj);
419 if (_taker && _taker !=
current())
425 _list.push_back(std::move(obj));
426 if (_taker && _taker !=
current())
435 while (_list.empty())
438 Type obj = std::move(_list.front());
440 return std::move(obj);
450 if (_taker && _taker !=
current())
461 return _list.empty();
470 #endif //STDEX_COROUTINE_H_
static thread_local Ordinator ordinator
std::function< void()> func
std::list< routine_t > indexes
routine_t create(std::function< void()> f)
void destroy(routine_t id)
std::result_of< Function()>::type await(Function &&func)
void consumer(routine_t id)
void push(const Type &obj)
std::vector< Routine * > routines
Routine(std::function< void()> f)
ResumeResult resume(routine_t id)
Ordinator(size_t ss=STACK_LIMIT)