C C 實現協程API包括上下文切換

2021-10-07 10:28:28 字數 3576 閱讀 9434

協程可以很方便在乙個執行緒中實現多個函式間的切換執行,如果某個函式需要等待,則可以切換到其他函式,這可以很大程度提高乙個執行緒的利用率,因此現在很流行;c++很多版本原生並沒有提供協程,但是由於c++支援內聯彙編,所以實現一套協程api並非難事,只要實現函式間的上下文切換,其他的就容易多了,上下文切換通常就是儲存當前函式的暫存器,由於是主動切換所以需要儲存的暫存器也就很少了,下面給出一種協程的實現方式:

coroutine.h

#ifndef m_coroutine_h

#define m_coroutine_h

//coroutine info

typedef struct

mcoroutine;

mcoroutine* alloc_co();

mcoroutine* pop_co();

bool createcoroutine(void (*task)(void*), void* args);

void schedule();

void runtask();

#define co_yield schedule();

#define print(str,...) printf(str##"\n",__va_args__)

#endif

coroutine.cpp

#include #include #include #include "coroutine.h"

//define the size of the coroutine stack

#define coroutine_stack_size 1024*1024*1 // 1m stack

#define max_coroutine 1000 // max coroutine num

//coroutine status flag

enum flags ;

std::listglobalcoroutinelist; // global coroutine list

static int coroutinerunningcount = 0; // the running count of coroutine

static mcoroutine cor_main = ; //main thread coroutine

static mcoroutine *currentcoroutine = &cor_main; //the current running coroutine

//assign a coroutine

mcoroutine *alloc_co()

auto *co = new mcoroutine();

globalcoroutinelist.push_back(co);

return co;

} globalcoroutinelist.push_back(co);

}// pop a coroutine from global coroutine list

mcoroutine *pop_co()

mcoroutine *co;

co = globalcoroutinelist.front();

globalcoroutinelist.pop_front();

return co;

}//this function will be run for the first time, and the task will be called by this function

static void coroutine_startup(mcoroutine *coroutine)

static void push_stack(unsigned int **stack_top_p_p, unsigned int val)

static bool init_stack(mcoroutine *coroutine)

static unsigned int id_num = 1;

static unsigned int get_id()

bool createcoroutine(void (*task)(void *), void *args)

void __fastcall release_coroutine(mcoroutine *coroutine)

__declspec(naked) void switch_context(mcoroutine *cur_coroutine, mcoroutine *dst_coroutine)

}void schedule()

switch(currentcoroutine->flag)

src_coroutine = currentcoroutine;

currentcoroutine = dst_coroutine;

switch_context(src_coroutine, dst_coroutine);

//print("switch_context over: src_coroutine:%d,dst_coroutine:%d", src_coroutine->id, dst_coroutine->id);

}void runtask() while (coroutinerunningcount);

}

main.cpp

#include "coroutine.h"

#include void task(void* num)

}int main()

runtask();

return 0;

}

cmakelists.txt

cmake_minimum_required(version 3.16)

project(mythread)

set(cmake_cxx_standard 14)

add_executable(test00 main.cpp coroutine.cpp coroutine.h)

執行結果:

start...

coroutine0 start...

coroutine0_0

coroutine1 start...

coroutine1_0

coroutine2 start...

coroutine2_0

coroutine3 start...

coroutine3_0

coroutine4 start...

coroutine4_0

coroutine5 start...

coroutine5_0

coroutine6 start...

coroutine6_0

coroutine7 start...

coroutine7_0

coroutine8 start...

coroutine8_0

coroutine9 start...

coroutine9_0

coroutine0_1

coroutine1_1

coroutine2_1

C C 協程的實現方式總結

1 利用 c 語言的 setjmp 和 longjmp,函式中使用 static local 的變數來儲存協程內部的資料。函式原型 int setjmp jmp buf envbuf void longjmp jmp buf envbuf,int val 先呼叫setjmp,用變數envbuf記錄當...

一種協程的 C C 實現

在前幾天接觸到了協程的概念,覺得很有趣。因為我可以使用乙個執行緒來實現乙個類似多執行緒的程式,如果使用協程來替代執行緒,就可以省去很多原子操作和記憶體柵欄的麻煩,大大減少與執行緒同步相關的系統呼叫。因為我只有乙個執行緒,而且協程之間的切換是可以由函式自己決定的。我有見過幾種協程的實現,因為沒有 c ...

gevent實現協程

1 yield實現 import time def task 1 while true print 1 time.sleep 0.1 yield def task 2 while true print 2 time.sleep 0.1 yield def main t1 task 1 建立迭代器 t...