首先,我不得不纠正先前我对协程的理解和定义,探索是有乐趣的,身为程序员,我不得不有些重构代码,和不断探索的“洁癖”(有部分探索是被动行为)。
那什么是协程?
就像上一篇文章说的一样,协程并非是线程(实际上协程出现要早于线程),协程是我们利用程序语言的语法语义实现的类似多任务的编程技巧。而协程其实就是一次函数调用,但又有少许不同,函数调用只有一个入口点并且在函数(也就是Java里的方法抑或叫行为)返回后结束;而协程在下次调用时可以在上次调用的返回点继续执行。
所以从某种意义上讲,函数可以称之为协程的特例;
从调用者与被调用者间的关系,可以将协程大致分为以下两类:
1. 对称协程
2. 非对称协程
若接触过协程,或少许浏览过上篇小文章,那您肯定会对yield不敢陌生,yield在协程中可移交函数控制权。
在这里举种对称协程的例子。
这里我们可以从我们熟悉的生产-消费驱动模型入手:
/*
* so maybe something like this
* 请原谅我这个OC coder
**/
#pragma mark - producer coroutine
void producer(){
while(YES){
createStaff();
addItem();
yield comsumer();
}
}
#pragma mark - comsumer coroutine
void cosumer(){
while (YES) {
consumeStaff();
removeItem();
yield producer();
}
}
相信伪代码的可读性是十分优良的,此处算法逻辑清晰可见,相信您可以明白,comsumer和producer各自执行着自定义行为,通知移交控制权,实现了表面上的多任务机制。(此种实现方式,想必多线程拥有诸多好处,比如资源竞争问题,和上下问切换等资源消耗问题)
C#,JavaScript,Lua等,已实现了类似yield,所以若用C实现了协程,相信会有进一步的理解。
所以有了如下经典代码:
int function(void) {
static int i, state = 0;
switch (state) {
case 0: goto LABEL0;
case 1: goto LABEL1;
}
LABEL0: /* start of function */
for (i = 0; i < 10; i++) {
state = 1; /* so we will come back to LABEL1 */
return i;
LABEL1:; /* resume control straight after the return */
}
}
我不得不说,初次见到这段代码,足足困惑了我10个单位时间才大致了解。单位为minute。
原因不多说,权且抛开它少了全局return不讲(由于缺少的全局return,在程序调用超出10次后,会有彩蛋(bug)出现,由于并非c++专家,所以只是做了些许猜测,彩蛋原因大致出在程序计数器)。其实程序本身不难理解,关键在Label1,Label1存在的意义在于,下次进入函数是,可以从上处的出口处继续执行,而如果Label1后在dosomestaff了呢,当然还需要Label2(笨笨的,有木有)。暂时说道这里。
很晚了,未完待续