协程演示源码/2

发布于 2024-10-05 14:23:05 字数 2190 浏览 7 评论 0原文

有人可以解释为什么这段代码在键盘上不起作用吗? 修改后的版本(带有虚函数)实际上可以工作 -
工作版本 - 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独夜无伴 2024-10-12 14:23:05

在非工作版本中,如果我更改

struct index : coroutine<index> {

struct indexX : coroutine<indexX> {

然后它会突然编译(使用 GCC)。显然,头文件中的某处已经定义了一个“索引”,它会干扰代码的索引。

In the non-working version, if I change

struct index : coroutine<index> {

to

struct indexX : coroutine<indexX> {

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.

靑春怀旧 2024-10-12 14:23:05

谢谢,这是一个可以在键盘上使用的紧凑版本 - http://codepad.org/6mBAyMhx

有趣的一点是,如果没有 noinline,它实际上会出现段错误。

#include <stdio.h>  // for printf
#include <memory.h> // for memcpy
#include <setjmp.h> // for setjmp
template <typename T> struct coroutine {
  volatile int state; coroutine():state(0){}
  volatile char *stkptrH,*stkptrL; jmp_buf PointA,PointB; char stack[1<<10];
  void yield( int value ) { char curtmp; stkptrL=(&curtmp)-16; if(setjmp(PointB)==0) 
    state=value,memcpy(stack,(char*)stkptrL,stkptrH-stkptrL),longjmp(PointA,1); }
  __attribute__((noinline)) int call_do_process() { char stktmp[1<<16];stkptrH=stktmp;((T*)this)->do_process();return 0;}
  int call() {if(setjmp(PointA)==0)(state?memcpy((char*)stkptrL,stack,stkptrH-stkptrL),longjmp(PointB,1):void(0)),call_do_process();return state;}
};

struct Index : coroutine<Index> { void do_process( void ) {
  for( int a=1;; ) { yield( a ); a++; }
}} F1;

struct Fibonacci : coroutine<Fibonacci> { void do_process( void ) {
  for( int a=0,b=1;; ) { yield( b ); b = b + a; a = b - a; }
}} F2;

int main( void ) {
  for( int i=0; i<20; i++ ) {
    printf( "%i:%i ", F1.call(), F2.call() );
  } printf( "\n" );
  return 0;
}

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.

#include <stdio.h>  // for printf
#include <memory.h> // for memcpy
#include <setjmp.h> // for setjmp
template <typename T> struct coroutine {
  volatile int state; coroutine():state(0){}
  volatile char *stkptrH,*stkptrL; jmp_buf PointA,PointB; char stack[1<<10];
  void yield( int value ) { char curtmp; stkptrL=(&curtmp)-16; if(setjmp(PointB)==0) 
    state=value,memcpy(stack,(char*)stkptrL,stkptrH-stkptrL),longjmp(PointA,1); }
  __attribute__((noinline)) int call_do_process() { char stktmp[1<<16];stkptrH=stktmp;((T*)this)->do_process();return 0;}
  int call() {if(setjmp(PointA)==0)(state?memcpy((char*)stkptrL,stack,stkptrH-stkptrL),longjmp(PointB,1):void(0)),call_do_process();return state;}
};

struct Index : coroutine<Index> { void do_process( void ) {
  for( int a=1;; ) { yield( a ); a++; }
}} F1;

struct Fibonacci : coroutine<Fibonacci> { void do_process( void ) {
  for( int a=0,b=1;; ) { yield( b ); b = b + a; a = b - a; }
}} F2;

int main( void ) {
  for( int i=0; i<20; i++ ) {
    printf( "%i:%i ", F1.call(), F2.call() );
  } printf( "\n" );
  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文