协程库的一些笔记
2014-10-13 17:07
148 查看
因为协程的好处,所以协程库现在有好多libtask,boost::coroutine,libco......
libtask很不错,以后或许会用。
boost我个人基本很少用。
腾讯的libco自己用汇编实现了swapcontext函数,不明觉厉(libtask也有ASM)。而且把epoll整合在了里面。
微信后台就用到了它.在chinaunix.net上的一个帖子中就说到了这个。不过暂不适合我。
还好云风实现过一个coroutine库,用的context系列函数,很精巧的封装,代码量很小, 也没附加啥其它特性。用来加深理解再好不过。
在 http://blog.codingnow.com/2012/07/c_coroutine.html 上有其相关说明。
不过代码没注释啥的,为了怕忘记一些体会,我按个人理解加了代码注释, 在上Github上保存了一份.
https://github.com/xcltapestry/coroutine (理解不深,如有错误欢迎指正).
至于下面是针对这个库的一些点,记录一下.
1. 结构体schedule与coroutine的参数意义
2. 64位指针的传递
3. 上下文内存和栈内存的一些处理
栈拷贝,按需分配
_save_stack(struct coroutine *C, char *top)
top - &dummy 确实用的好.
top是栈顶地址, 通过top - &dummy得到栈的实际所需大小分配组C->stack,
然后在resume时可以从这弄回去.
引用:
"因为,在我的应用场合,coroutine 切换的那一刻,使用的堆栈并不多(它可能调用一些需要大量堆栈的库函数,但那些库函数中并不会发生切换),所以,在切换的时刻做栈拷贝是可以接受的。coroutine 切换并不算频繁,这个切换成本是可控的。"
char stack[STACK_SIZE]; //运行时,co上下文用的就是这块内存
引用:
"其次,我不希望使用 coroutine 的人太考虑 stack 大小的问题。就是说,用户在 coroutine 内可以使用的 C stack 大小和主线程一样多。"
4. 在开发32/64位程序时,以后应当多使用ptrdiff_t,uintptr_t 和 uint32_t这类为了跨平台而定义的东东.
这类东西定义在 stdint.h 中. 在Windows下我用vs2005尝试时,悲剧的发现2005不支持这个,查到的解决方法是访问 http://www.azillionmonkeys.com/qed/pstdint.h 然后将里面的内容复制到自己新增的stdint.h中即可用了,以后如vs2010支持了再去掉就行了.
协程库这东西不简单。
MAIL: xcl_168@aliyun.com
BLOG: http://blog.csdn.net/xcl168
libtask很不错,以后或许会用。
boost我个人基本很少用。
腾讯的libco自己用汇编实现了swapcontext函数,不明觉厉(libtask也有ASM)。而且把epoll整合在了里面。
微信后台就用到了它.在chinaunix.net上的一个帖子中就说到了这个。不过暂不适合我。
还好云风实现过一个coroutine库,用的context系列函数,很精巧的封装,代码量很小, 也没附加啥其它特性。用来加深理解再好不过。
在 http://blog.codingnow.com/2012/07/c_coroutine.html 上有其相关说明。
不过代码没注释啥的,为了怕忘记一些体会,我按个人理解加了代码注释, 在上Github上保存了一份.
https://github.com/xcltapestry/coroutine (理解不深,如有错误欢迎指正).
至于下面是针对这个库的一些点,记录一下.
1. 结构体schedule与coroutine的参数意义
struct schedule { char stack[STACK_SIZE]; //运行时,co上下文用的就是这块内存. 厉害 ucontext_t main; //上下文信息 int nco; //实际的co指针个数 int cap; //co指针数组大小 int running; // 当前处理的co数组id 或 -1 struct coroutine **co; //co指针数组 }; // ptrdiff_t 用于表示指针间的"距离",对于指针加减的结果可用这个类型来表示. struct coroutine { coroutine_func func; //用户自定义的函数 void *ud; //用户自定义的函数,所传进来的参数,在此为main中的statuc arg ucontext_t ctx; //上下文信息就不用多说了 struct schedule * sch; //指向co所归属的Sch. ptrdiff_t cap; //容量 ptrdiff_t size; //占用的栈大小 int status; // COROUTINE_SUSPEND/COROUTINE_READY char *stack; //在yield/resume时发挥保存和恢复作用 };
2. 64位指针的传递
//注意这里从兼容性角度把S这个指针拆了下,原因是大部份编译器在32/64位下, //sizeof(指针)返回的长度是不一样的, 32位下是4个字节,64位下是8个字节 //所以在makecontext()的这个可变参数中,将其拆分成了两个32位的指针来传. //附:在执行地址运算时,多用 uintptr_t 和 uint32_t,更清晰,安全性与兼容性更好 uintptr_t ptr = (uintptr_t)S; makecontext(&C->ctx, (void (*)(void)) mainfunc, 2, (uint32_t)ptr, (uint32_t)(ptr>>32));
3. 上下文内存和栈内存的一些处理
栈拷贝,按需分配
_save_stack(struct coroutine *C, char *top)
top - &dummy 确实用的好.
top是栈顶地址, 通过top - &dummy得到栈的实际所需大小分配组C->stack,
然后在resume时可以从这弄回去.
引用:
"因为,在我的应用场合,coroutine 切换的那一刻,使用的堆栈并不多(它可能调用一些需要大量堆栈的库函数,但那些库函数中并不会发生切换),所以,在切换的时刻做栈拷贝是可以接受的。coroutine 切换并不算频繁,这个切换成本是可控的。"
char stack[STACK_SIZE]; //运行时,co上下文用的就是这块内存
引用:
"其次,我不希望使用 coroutine 的人太考虑 stack 大小的问题。就是说,用户在 coroutine 内可以使用的 C stack 大小和主线程一样多。"
4. 在开发32/64位程序时,以后应当多使用ptrdiff_t,uintptr_t 和 uint32_t这类为了跨平台而定义的东东.
这类东西定义在 stdint.h 中. 在Windows下我用vs2005尝试时,悲剧的发现2005不支持这个,查到的解决方法是访问 http://www.azillionmonkeys.com/qed/pstdint.h 然后将里面的内容复制到自己新增的stdint.h中即可用了,以后如vs2010支持了再去掉就行了.
协程库这东西不简单。
MAIL: xcl_168@aliyun.com
BLOG: http://blog.csdn.net/xcl168
相关文章推荐
- 协程库的一些笔记
- [Eclipse笔记]一些基本概念
- SCJP一些笔记
- [转贴]准备SCJP的时候做的一些笔记
- 一些乱七八糟的笔记
- 我的设计模式之旅(1)——学习的原则和一些笔记
- 关于ccna的一些学习笔记
- [转贴]准备SCJP的时候做的一些笔记
- 我的智能网学习笔记.一些乱七八糟的东西.
- [笔记]3.软件代码中的BUG问题的一些记录
- SCJP一些笔记 hanic [原作]
- 以前看书时记得一些笔记(二),很早了,现在再看都有些看不懂了
- 阅读笔记:库绑定 - 我们应该让它更精确一些
- ViewState的一些学习笔记
- 以前看书时记得一些笔记(三),很早了,现在再看都有些看不懂了
- 准备SCJP的时候做的一些笔记
- tomcat3的一些知识--tomcat笔记1
- 以前看书时记得一些笔记(一),很早了,现在再看都有些看不懂了
- 发布biztalk的一些onenote笔记,是一个mht格式的,希望对大家有帮助
- UML学习笔记(二):复习面向对象的一些基本概念