Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <ucontext.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <setjmp.h>
- struct fiber_t
- {
- ucontext_t fib;
- jmp_buf jmp;
- };
- struct fiber_ctx_t
- {
- void(* fnc)(void*);
- void* ctx;
- jmp_buf* cur;
- ucontext_t* prv;
- };
- class Coroutine{
- private:
- fiber_t fib;
- public:
- virtual void execute() =0;
- void yield(Coroutine *next=NULL);
- void attach();
- Coroutine(long stackSize);
- virtual ~Coroutine();
- };
- static void fiber_start_fnc(void* p)
- {
- fiber_ctx_t* ctx = (fiber_ctx_t*)p;
- void* uctx = ctx->ctx;
- if (_setjmp(*ctx->cur) == 0)
- {
- ucontext_t tmp;
- swapcontext(&tmp, ctx->prv);
- }
- Coroutine *coroutine = (Coroutine *)uctx;
- coroutine->execute();
- }
- inline void create_fiber(fiber_t* fib, void* uctx)
- {
- getcontext(&fib->fib);
- size_t const stack_size = 64*1024;
- fib->fib.uc_stack.ss_sp = (::malloc)(stack_size);
- fib->fib.uc_stack.ss_size = stack_size;
- fib->fib.uc_link = 0;
- ucontext_t tmp;
- fiber_ctx_t ctx = {NULL, uctx, &fib->jmp, &tmp};
- makecontext(&fib->fib, (void(*)())fiber_start_fnc, 1, &ctx);
- swapcontext(&tmp, &fib->fib);
- }
- inline void switch_to_fiber(fiber_t& fiber, fiber_t& prevfiber)
- {
- if (_setjmp(prevfiber.jmp) == 0)
- _longjmp(fiber.jmp, 1);
- }
- __thread fiber_t fibmain;
- __thread bool initialized_fibmain = false;
- void Coroutine::yield(Coroutine *next)
- {
- if (next==NULL)
- switch_to_fiber(fibmain, fib);
- else
- switch_to_fiber(next->fib, fib);
- }
- void Coroutine::attach()
- {
- switch_to_fiber(fib, fibmain);
- }
- Coroutine::Coroutine(long stackSize)
- {
- if (!initialized_fibmain)
- {
- create_fiber(&fibmain, NULL);
- initialized_fibmain = true;
- }
- create_fiber(&fib, this);
- }
- Coroutine::~Coroutine()
- {
- free(fib.fib.uc_stack.ss_sp);
- }
- Coroutine *A,*B;
- class CoroutineA : public Coroutine{
- public:
- CoroutineA(): Coroutine(8*1024){};
- void execute()
- {
- printf("CoroutineA\n");
- for (int i=0; i<100; i++)
- {
- printf("i=%d\n",i);
- yield(B);
- }
- printf("after yield CoroutineA\n");
- }
- };
- class CoroutineB : public Coroutine{
- public:
- CoroutineB(): Coroutine(8*1024){};
- void execute()
- {
- printf("CoroutineB\n");
- for (int i=0; i<100; i++)
- {
- printf("i=%d\n",i);
- yield(A);
- }
- printf("after yield CoroutineB\n");
- }
- };
- int main()
- {
- A = new CoroutineA();
- B = new CoroutineB();
- A->attach();
- delete A;
- delete B;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment