2014年3月2日星期日

探索那些不常见的控制流(1)

http://coolshell.cn/articles/10975.html
这篇文章介绍了一个“蝇量级” C 语言协程库的实现。

里面使用宏封装了下,不过我不喜欢宏,觉得宏把简单的东西隐藏而不可见。因为我并不会真正直接用这些宏,只是为了搞清楚如何在C里实现yiled,去掉宏之后,我们可以很清晰的看懂代码的结构和流程。

下面的代码从http://www.chiark.greenend.org.uk/~sgtatham/coroutine.h解析:

#include <stdio.h>
#include <stdlib.h>

/**
 *单线程coroutine,不可重入
 */
int function(void){
static int i,state = 0;
switch(state){
case 0:
for(i=0;i<10;i++){
state = 1;
return i;
case 1:;
}
}
}

/**
 *多线程coroutine,可重入
 */
typedef void* ccr_context_handle;
typedef struct tag_ccr_context{
int state;
int i;
}ccr_context;

int ascending(ccr_context_handle* ccr_context_handle_pointer) {
ccr_context* this = (ccr_context*)*ccr_context_handle_pointer;
if(!this){
this = malloc(sizeof(ccr_context));
*ccr_context_handle_pointer = this;
this->state = 0;
}
if(this){
switch(this->state){
case 0:;
for (this->i=0;this->i<10; this->i++) {
this->state = 1;
return this->i;
case 1:;
}
}
free(*ccr_context_handle_pointer);
*ccr_context_handle_pointer = 0;
return -1;
}
}

/**
 *C测试代码
 */
int main(){
printf("\n");
int i=0;
for(i=0;i<10;i++){
printf("%d",function());
}
printf("\n");

ccr_context_handle handle = 0;
do {
int ret = ascending(&handle);
if(ret!=-1){
printf("%d",ret);
}
}while(handle);
printf("\n");

return 0;
}

当我继续搜索,上述代码在这个页面出现:
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
这个页面里描述了在C语言里做coroutine。以及一个典型的生产者消费者模型。在C里面做协程并不轻松,底下更本质的原因是因为C语言里对continuation的支持很低阶,什么是continuation我们会在后面的节里给出。






没有评论:

发表评论