close

關於 coroutine , setjmp , longjmp implement 執行速度 比 ucontext 要來的快 ,

以下是 1024cores 強者 , 來自戰鬥民族的蘇聯人,寫了一篇關於 setjmp and longjmp的文章 :

http://www.1024cores.net/home/lock-free-algorithms/tricks/fibers

以及他用到 setjmp , longjmp 的工具 :

http://www.1024cores.net/home/relacy-race-detector

從這工具 source code , 我寫了 一支小小的測試程式 ,  先簡單寫一下 ,

難一點的應用 後面再來寫 ~~~

1. marscoro.hpp

#ifndef TRANS_H
#define TRANS_H

#include <ucontext.h>
#include <memory.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.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;
};


static void fiber_start_fnc(void* p)
{
    struct fiber_ctx_t* ctx = (struct fiber_ctx_t*)p;
    void (*volatile ufnc)(void*) = ctx->fnc;
    void* volatile uctx = ctx->ctx;
    if (_setjmp(*ctx->cur) == 0)
    {
        ucontext_t tmp;
        swapcontext(&tmp, ctx->prv);
    }
    ufnc(uctx);
}

inline void create_main_fiber(fiber_t& fib)
{
    memset(&fib, 0, sizeof(fib));
}

inline void delete_main_fiber(fiber_t& fib)
{
    (void)fib;
}

inline void create_fiber(fiber_t& fib, void(*ufnc)(void*), void* uctx)
{
    size_t const stack_size = 64*1024;
    getcontext(&fib.fib);
    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;
    struct fiber_ctx_t ctx = {ufnc, uctx, &fib.jmp, &tmp};
    makecontext(&fib.fib, (void(*)())fiber_start_fnc, 1, &ctx);
    swapcontext(&tmp, &fib.fib);
}

inline void delete_fiber(fiber_t& fib)
{
    //(::free)(fib.uc_stack.ss_sp);
}

inline void switch_to_fiber(fiber_t& fib, fiber_t& prv)
{
    if (_setjmp(prv.jmp) == 0)
        _longjmp(fib.jmp, 1);
}

#endif

 

2.  marscoro.cpp

#include <ucontext.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include "marscoro.hpp"

    struct fiber_t main_fiber_ ;
    struct fiber_t fib1 ;
    struct fiber_t fib2 ;

void testfunc1(void* x)
{
    printf("testfunc1 \n") ;
    while(1)
    {
        printf("hello1 \n") ;
        switch_to_fiber(fib2,fib1);
        sleep(1) ;
    }
}
void testfunc2(void* x)
{
    int icnt = 0 ;
    printf("testfunc2 \n") ;
    while(1)
    {
        printf("hello2 \n") ;
        ++icnt ;
        if(icnt > 5)
            switch_to_fiber(main_fiber_,fib2);
        else
            switch_to_fiber(fib1,fib2);

        sleep(1) ;
    }
}

typedef void (*fnx)(void*) ;

int main()
{

    create_main_fiber(main_fiber_);

    fnx f1 = &testfunc1 ;
    int i1 = 0 ;
    create_fiber(fib1,f1,(void*)(intptr_t)i1);


    fnx f2 = &testfunc2 ;
    int i2 = 1 ;
    create_fiber(fib2,f2,(void*)(intptr_t)i2);

    switch_to_fiber(fib1,main_fiber_);

    printf("going to end \n") ;
    delete_main_fiber(main_fiber_) ;

}

 

g++ --std=c++0x marscoro.cpp -o marscoro.exe

output :

testfunc1
hello1
testfunc2
hello2
hello1
hello2
hello1
hello2
hello1
hello2
hello1
hello2
hello1
hello2
going to end

 

arrow
arrow
    全站熱搜

    hedgezzz 發表在 痞客邦 留言(0) 人氣()