I'm playing around with boost::context a bit, making a little task scheduler. A minimal proof of concept.
After being able to create tasks and have them run according to the scheduler, it occurred to me to add the clone( ) functionality, using setjmp( ). However, when I try to run the cloned task, I get a nice 'SIGSEGV` error:
#include <boost/context/continuation.hpp>
#include <csetjmp>
#include <iostream>
namespace ctx = boost::context;
enum CoroState {
    Finish = 0,
    Ready
};
using EntryPoint = void (*)( );
struct Coro {
    ~Coro( ) {
        if( next != this ) {
            prev->next = next;
            next->prev = prev;
        }
    }
    Coro( EntryPoint ep ) :
        state( CoroState::Ready ),
        entryPoint( ep ),
        clone( false ),
        next( this ),
        prev( this ) {
    }
    Coro( EntryPoint ep, Coro *curr ) :
        state( CoroState::Ready ),
        entryPoint( ep ),
        clone( false )
    {
        next = curr;
        prev = curr->prev;
        curr->prev = this;
        prev->next = this;
    }
    Coro( Coro *origin ) :
        Coro( origin->entryPoint, origin )
    {
        clone = true;
    }
    CoroState state;
    EntryPoint entryPoint;
    bool clone;
    Coro *next;
    Coro *prev;
    std::string name;
    jmp_buf jmpBuf;
    ctx::continuation continuation;
};
static Coro *ActiveCoro = nullptr;
static ctx::continuation wrapper( ctx::continuation &&sink ) {
    ActiveCoro->continuation = std::move( sink );
    if( ActiveCoro->clone ) {
        std::longjmp( ActiveCoro->jmpBuf, 1 );
    } else {
        ActiveCoro->entryPoint( );
    }
    ActiveCoro->state = CoroState::Finish;
    return std::move( ActiveCoro->continuation );
}
static void yield( ) {
    ActiveCoro->continuation = ActiveCoro->continuation.resume( );
}
static Coro &createCoro( EntryPoint ep ) {
    Coro *result;
    if( !ActiveCoro ) {
        ActiveCoro = new Coro( ep );
        result = ActiveCoro;
    } else {
        result = new Coro( ep, ActiveCoro );
    }
    return *result;
}
bool clone( ) {
    auto newCoro = new Coro( ActiveCoro );
    return setjmp( newCoro->jmpBuf );
}
void runLoop( ) {
    while( ActiveCoro ) {
        if( ActiveCoro->continuation ) {
            ActiveCoro->continuation = ActiveCoro->continuation.resume( );
        } else {
            ActiveCoro->continuation = ctx::callcc( wrapper );
        }
        if( ActiveCoro->state == CoroState::Finish ) {
            if( ActiveCoro->next == ActiveCoro ) {
                delete ActiveCoro;
                break;
            } else {
                auto toDelete = ActiveCoro;
                ActiveCoro = ActiveCoro->next;
                toDelete->prev->next = toDelete->next;
                toDelete->next->prev = toDelete->prev;
                delete toDelete;
            }
        }
        ActiveCoro = ActiveCoro->next;
    }
}
static void Worker( ) {
    for( int idx = 0; idx < 5; ++idx ) {
        std::cout << ActiveCoro->name << ", idx " << idx << std::endl;
        yield( );
    }
    std::cout << ActiveCoro->name << " terminado.\n";
}
static void Master( ) {
    std::cout << "Entrando en Master.\n";
    createCoro( Worker ).name = "Worker 1";
    createCoro( Worker ).name = "Worker 2";
    createCoro( Worker ).name = "Worker 3";
    std::cout << "Master ha creado los hijos. Esperando.\n";
    if( clone( ) ) {
        std::cout << "Clon de Master terminado\n";
    } else {
        std::cout << "Master terminado.\n";
    }
}
int main( ) {
    std::ios::sync_with_stdio( false );
    createCoro( Master ).name = "Master";
    runLoop( );
    std::cout << std::endl;
    return 0;
}
The problem is unique to the clone( ) functionality. If I comment this part:
/*
if( clone( ) ) {
    std::cout << "Clon de Master terminado\n";
} else {
    std::cout << "Master terminado.\n";
}
*/
everything works fine again.
- Is it possible to get the 
clone( )functionality in this way ? - How to it ?
 
Aucun commentaire:
Enregistrer un commentaire