Domanda

Qualcuno può spiegare perché questo codice non funziona su tastiera codici ? Una versione modificata (con funzione virtuale) in realtà funziona anche se -
versione di lavoro - http://codepad.org/5rRIg5zT
Non funziona la versione (in basso) - http://codepad.org/4PO2rBqS
Voglio dire, è che in realtà valida C ++, o tastiera codici compilatore è sbagliato?

Aggiornamento: c'è un altro modo per fare questo lavoro - http://codepad.org/j6GAKXov ma la sua non del tutto automatica.

#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;
}
È stato utile?

Soluzione

Nella versione non funzionante, se cambio

struct index : coroutine<index> {

a

struct indexX : coroutine<indexX> {

allora compila un tratto (utilizzando GCC). Pare che ci sia un 'indice' da qualche parte già definito in un file di intestazione che interferisce con l'indice del codice.

Altri suggerimenti

Grazie, quindi ecco una versione compatta che fa lavoro sulla tastiera codici - http://codepad.org/6mBAyMhx
Un punto interessante è che in realtà segfaults lì senza che 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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top