2010-12-04 9 views
1

Kann jemand erklären, warum dieser Code nicht funktioniert Codepad? Eine modifizierte Version (mit virtueller Funktion) tatsächlich funktioniert aber -
Arbeitsversion - http://codepad.org/5rRIg5zT
Problem Version (unten) - http://codepad.org/4PO2rBqS
ich meine, ist, dass tatsächlich gültig C++ oder Codepad Compiler falsch?Coroutine-Demo-Quelle/2

Update: Es gibt einen anderen Arbeitsweg, dies zu tun - http://codepad.org/j6GAKXov aber es ist nicht ganz automatisch.

#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; 
} 
+0

Ich bekomme einen Kompilierungsfehler mit dem, den Sie in dieser Frage geschrieben haben. Was bekommst du? –

+0

Es funktioniert mit gcc 4.3 +/intelc/VS auf Windows, gcc 4 auf iphone – Shelwien

+0

Warum haben Sie nicht einfach einen Link zu Codepad mit Ihrem Code? – EboMike

Antwort

2

In der nicht-funktionsfähige Version, wenn ich

ändern
struct index : coroutine<index> { 

zu

struct indexX : coroutine<indexX> { 

dann plötzlich kompiliert (mit GCC). Anscheinend ist irgendwo in einer Header-Datei ein 'Index' definiert, der den Index Ihres Codes stört.

1

Danke, also hier ist eine kompakte Version, die Arbeit auf Codepad tut - http://codepad.org/6mBAyMhx
Ein interessanter Punkt ist, dass es ohne diese noinline es tatsächlich Segfaults.

#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; 
} 
+0

Hallo Shelwien überprüfen Sie hier: http://ideone.com/KmCRvE –

+0

Scheint das gleiche wie Codepad? – Shelwien

+0

Ich denke es ist besser. Mehr langs, keine segfaults auf ur code. –