比较几个 C 语言协程实现

本文对比了多个C语言协程实现,包括coroutine.h、protothreads、libdill & libmill以及state-threads。coroutine.h适用于资源紧张的环境,protothreads轻量级且跨平台,libdill适合服务端程序,而state-threads则针对高性能网络服务器。在Windows上编译libdill和coroutine.h时需要注意特定的编译选项。
摘要由CSDN通过智能技术生成

比较几个 C 语言协程实现

coroutine.h

作者:

https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

这个是用宏方式实现的。用于对资源紧张的客户端。

protothreads

另外一个可选的协程实现是 protothreads (pt):

http://dunkels.com/adam/download/pt-1.4.tar.gz

这些用在客户端都合适,极轻量级,跨windows/linux/arm平台。

libdill & libmill

这个适合编写服务端协程程序。

http://libdill.org/

在 Linux 编译非常简单:

$ wget http://libdill.org/libdill-2.14.tar.gz
$ tar -xzf libdill-2.14.tar.gz 
$ cd libdill-2.14
$ ./configure
$ make
$ sudo make install

在 Windows 上用 mingw64,我按下面的方式编译成功(未做使用测试):

$ wget http://libdill.org/libdill-2.14.tar.gz
$ tar -xzf libdill-2.14.tar.gz 
$ cd libdill-2.14
$ ./configure
  • DEBUG:

      $ ./libtool --tag=CC --mode=link x86_64-w64-mingw32-gcc -std=gnu99 -fvisibility=hidden -DDILL_EXPORTS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -g -O2 -no-undefined -version-info 3:0:0  -o libdill.la -rpath /mingw64/lib -lWs2_32
    
  • RELEASE:

      $ ./libtool --tag=CC --mode=link x86_64-w64-mingw32-gcc -std=gnu99 -fvisibility=hidden -DDILL_EXPORTS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -O3 -no-undefined -version-info 3:0:0  -o libdill.la -rpath /mingw64/lib -lWs2_32
    

生成结果在 .libs/ 目录里:

libdill.a  libdill.dll.a  libdill.la  libdill.lai  libdill-3.dll

建立在它之上有一个有名的类似 go 的协程库: libmill,它可用像写go 一样写C协程程序。

http://libmill.org/

libdill 功能非常强大,编译时根据可以需要裁剪。

state-threads

网络服务器使用以上协程库,都力不从心,推荐 state-threads,这个是用协程库实现的网络服务器,高可用,高性能,可用根据需要在上面定制:

http://state-threads.sourceforge.net/

Windows 版本64位不好用(32位好像可用),Linux 版本测试可用。

coroutine.h 的源码

如果仅仅写个简单的协程测试程序,建议使用 coroutine.h 或者 protothreads。下面是 coroutine.h 的源码,亲测可用。VS 编译时会报错误:

error C2051: case expression not constant

解决方法就是编译器配置的问题,只需要在项目属性配置页:C++/常规general/调式格式信息debug info format 中设置为:程序数据库/Zi (切记不使用:用于编辑并继续的…/ZI)

/* coroutine.h
 * 
 * Coroutine mechanics, implemented on top of standard ANSI C. See
 * https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html for
 * a full discussion of the theory behind this.
 * 
 * To use these macros to define a coroutine, you need to write a
 * function that looks something like this.
 * 
 * [Simple version using static variables (scr macros)]
 * int ascending (void) {
 *    static int i;
 * 
 *    scrBegin;
 *    for (i=0; i<10; i++) {
 *       scrReturn(i);
 *    }
 *    scrFinish(-1);
 * }
 * 
 * [Re-entrant version using an explicit context structure (ccr macros)]
 * int ascending (ccrContParam) {
 *    ccrBeginContext;
 *    int i;
 *    ccrEndContext(foo);
 *
 *    ccrBegin(foo);
 *    for (foo->i=0; foo->i<10; foo->i++) {
 *       ccrReturn(foo->i);
 *    }
 *    ccrFinish(-1);
 * }
 * 
 * In the static version, you need only surround the function body
 * with `scrBegin' and `scrFinish', and then you can do `scrReturn'
 * within the function and on the next call control will resume
 * just after the scrReturn statement. Any local variables you need
 * to be persistent across an `scrReturn' must be declared static.
 * 
 * In the re-entrant version, you need to declare your persistent
 * variables between `ccrBeginContext' and `ccrEndContext'. These
 * will be members of a structure whose name you specify in the
 * parameter to `ccrEndContext'.
 * 
 * The re-entrant macros will malloc() the state structure on first
 * call, and free() it when `ccrFinish' is reached. If you want to
 * abort in the middle, you can use `ccrStop' to free the state
 * structure immediately (equivalent to an explicit return() in a
 * caller-type routine).
 * 
 * A coroutine returning void type may call `ccrReturnV',
 * `ccrFinishV' and `ccrStopV', or `scrReturnV', to avoid having to
 * specify an empty parameter to the ordinary return macros.
 * 
 * Ground rules:
 *  - never put `ccrReturn' or `scrReturn' within an explicit `switch'.
 *  - never put two
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

车斗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值