How to use boost context correctly

Viewed 3858

I want to implement a job system for my game engine using fibers. After searching the internet for a good c++ implementation of fibers, I found that Boost.Context is a good starting point.

Update 1: I want to implement my own scheduling algorithm, thus Boost.Fiber, Boost.Coroutine, Boost.Coroutine2 are not suitable for my implementation.

After compiling boost for x64 architecture and trying to run the basic example from the boost documentation I got the following exception:

boost::context::detail::forced_unwind at memory location

This is the code I tried to run (Visual Studio 2015 enterprise edition, windows 7):

#include <iostream>
#include <boost\context\continuation.hpp>
namespace ctx=boost::context;
int main()
{
    ctx::continuation source=ctx::callcc
    (
        [](ctx::continuation && sink)
        {
            int a=0;
            int b=1;
            for(;;)
            {
                sink=sink.resume(a);
                auto next=a+b;
                a=b;
                b=next;
            }
            return std::move(sink);
        }
    );
    for (int j=0;j<10;++j) {
        std::cout << source.get_data<int>() << " ";
        source=source.resume();
    }
    return 0;
}

The code ran correctly (correct output: 0 1 1 2 3 5 8 13 21 34 55), but when it finished the run I got the exception.

Update 2: The exception occurs only for the release build

I want to ask two questions regarding boost context:

1) What caused the stack unwinding exception, and how to avoid it?

2) I found the boost documentation a bit shallow, and couldn't find any other tutorial on how to use boost context. Can you direct me to some good sources/tutorials about boost context?

3 Answers

After return 0, the source object is not in the position which be destroyed.

Something like:

namespace ctx = boost::context;
int a;
bool stop = false;
{
    ctx::continuation source = ctx::callcc(
        [&stop, &a](ctx::continuation && sink) {
        a = 0;
        int b = 1;
        for (;;) {
            sink = sink.resume();
            if (stop)
                break;
            int next = a + b;
            a = b;
            b = next;
        }
        return std::move(sink);
    });
    for (int j = 0; j < 10; ++j) {
        std::cout << a << " ";
        source = source.resume();
    }
    stop = true;
    source.resume();
}

If you are running on Windows and the error only occurs in Release mode, you may need to check that your compiler flags are set appropriately.

From here:

Windows using fcontext_t: turn off global program optimization (/GL) and change /EHsc (compiler assumes that functions declared as extern "C" never throw a C++ exception) to /EHs (tells compiler assumes that functions declared as extern "C" may throw an exception).

Related