协程演示源码/2
有人可以解释为什么这段代码在键盘上不起作用吗? 修改后的版本(带有虚函数)实际上可以工作 -
工作版本 - http://codepad.org/5rRIg5zT
无法工作的版本(如下) - http://codepad.org/4PO2rBqS
我的意思是,这实际上是有效的 C++,还是键盘编译器错误?
更新:还有另一种工作方法可以做到这一点 - http://codepad.org/j6GAKXov 但它并不完全自动。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned char byte;
#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE __declspec(noinline)
#endif
#include <setjmp.h>
enum{
STKPAD=1<<16,
STKSAV=1<<10
};
template <typename T>
struct coroutine {
volatile uint state;
volatile char* stkptrH;
volatile char* stkptrL;
jmp_buf PointA, PointB;
char stack[STKSAV];
coroutine() { state=0; }
NOINLINE // necessary for IntelC + my_setjmp.h
void yield( int value ) {
char curtmp; stkptrL=(&curtmp)-16; // -16 is necessary for MSC
if( setjmp(PointB)==0 ) {
state = value;
memcpy( stack, (char*)stkptrL, stkptrH-stkptrL );
longjmp(PointA,1);
}
}
NOINLINE // necessary for MSC, to avoid allocation of stktmp before setjmp()
void call_do_process() {
char stktmp[STKPAD]; stkptrH = stktmp;
((T*)this)->do_process();
}
uint call( void ) {
if( setjmp(PointA)==0 ) {
if( state ) {
memcpy( (char*)stkptrL, stack, stkptrH-stkptrL );
longjmp(PointB,1);
}
call_do_process();
}
return state;
}
};
struct index : coroutine<index> {
void do_process( void ) {
uint a=1;
while(1) {
yield( a );
a++;
}
}
} F1;
struct fibonacci : coroutine<fibonacci> {
void do_process( void ) {
uint a=0,b=1;
while(1) {
yield( b );
b = b + a;
a = b - a;
}
}
} F2;
int main( int argc, char** argv ) {
for( int i=0; i<20; i++ ) {
printf( "%i:%i ", F1.call(), F2.call() );
} printf( "\n" );
return 0;
}
Can somebody explain why this code doesn't work on codepad?
A modified version (with virtual function) actually works though -
Working version - http://codepad.org/5rRIg5zT
Not working version (below) - http://codepad.org/4PO2rBqS
I mean, is that actually valid C++, or codepad compiler is wrong?
Update: there's another working way to do this - http://codepad.org/j6GAKXov
but its not quite automatic.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned char byte;
#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE __declspec(noinline)
#endif
#include <setjmp.h>
enum{
STKPAD=1<<16,
STKSAV=1<<10
};
template <typename T>
struct coroutine {
volatile uint state;
volatile char* stkptrH;
volatile char* stkptrL;
jmp_buf PointA, PointB;
char stack[STKSAV];
coroutine() { state=0; }
NOINLINE // necessary for IntelC + my_setjmp.h
void yield( int value ) {
char curtmp; stkptrL=(&curtmp)-16; // -16 is necessary for MSC
if( setjmp(PointB)==0 ) {
state = value;
memcpy( stack, (char*)stkptrL, stkptrH-stkptrL );
longjmp(PointA,1);
}
}
NOINLINE // necessary for MSC, to avoid allocation of stktmp before setjmp()
void call_do_process() {
char stktmp[STKPAD]; stkptrH = stktmp;
((T*)this)->do_process();
}
uint call( void ) {
if( setjmp(PointA)==0 ) {
if( state ) {
memcpy( (char*)stkptrL, stack, stkptrH-stkptrL );
longjmp(PointB,1);
}
call_do_process();
}
return state;
}
};
struct index : coroutine<index> {
void do_process( void ) {
uint a=1;
while(1) {
yield( a );
a++;
}
}
} F1;
struct fibonacci : coroutine<fibonacci> {
void do_process( void ) {
uint a=0,b=1;
while(1) {
yield( b );
b = b + a;
a = b - a;
}
}
} F2;
int main( int argc, char** argv ) {
for( int i=0; i<20; i++ ) {
printf( "%i:%i ", F1.call(), F2.call() );
} printf( "\n" );
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在非工作版本中,如果我更改
为
然后它会突然编译(使用 GCC)。显然,头文件中的某处已经定义了一个“索引”,它会干扰代码的索引。
In the non-working version, if I change
to
then it suddenly compiles (using GCC). Apparently there is an 'index' already defined somewhere in a header file that interferes with the index of your code.
谢谢,这是一个可以在键盘上使用的紧凑版本 - http://codepad.org/6mBAyMhx
有趣的一点是,如果没有 noinline,它实际上会出现段错误。
Thanks, so here's a compact version which does work on codepad - http://codepad.org/6mBAyMhx
An interesting point is that it actually segfaults there without that noinline.