c++boostboost-context

boost context class


I found boost has a class called context which is used for context switching, right?

I try to Google it but did not found any document or example. I am just wondering if anyone can provide some information.


Solution

  • Boost::Context is an official part of Boost in version 1.51.0 and up. See http://www.boost.org/doc/libs/1_51_0/libs/context/doc/html/index.html for information about it. Unfortunately the documentation is slightly different than the implementation, and some things have changed in SVN, so you'll need to read the header files a little bit.

    Here is an example I wrote the other day showing Boost::Context to make simple coroutines using Boost 1.51.0+latest SVN:

    #include <array>
    #include <functional>
    
    #include <boost/context/all.hpp>
    
    class Coroutine {
        public:
        Coroutine() :
            my_context(boost::context::make_fcontext(
                stack.data() + stack.size(),
                stack.size(),
                Coroutine::dispatch
            ))
        {}
        virtual ~Coroutine() {}
    
        void operator()() {
            boost::context::jump_fcontext(&yield_context, my_context, reinterpret_cast<intptr_t>(this));
        }
    
        protected:
        void yield() {
            boost::context::jump_fcontext(my_context, &yield_context, 0);
        }
    
        virtual void call() = 0;
    
        private:
        static void dispatch(intptr_t coroutine_ptr) {
            Coroutine *coroutine = reinterpret_cast<Coroutine *>(coroutine_ptr);
            coroutine->call();
            while (true) coroutine->yield();
        }
    
        private:
        boost::context::fcontext_t *my_context;
        boost::context::fcontext_t yield_context;
        std::array<intptr_t, 64*1024> stack;
    };
    
    struct A : public Coroutine {
        void call() {
            std::cerr << "A went to the store one day.\n";
            yield();
            std::cerr << "A was looking for groceries.\n";
            yield();
            std::cerr << "A finally found what she was looking for.\n";
        }
    };
    
    struct B : public Coroutine {
        void call() {
            std::cerr << "B went to the store one day.\n";
            yield();
            std::cerr << "B was looking for replacement tires.\n";
            yield();
            std::cerr << "B didn't find anything at all.\n";
            yield();
            std::cerr << "B went to another store.\n";
            yield();
            std::cerr << "B got the tires installed there.\n";
        }
    };
    
    struct C : public Coroutine {
        void call() {
            std::cerr << "C went to the store one day.\n";
            yield();
            std::cerr << "C was looking for USB drives.\n";
            yield();
            std::cerr << "C found several with competitive pricing.\n";
            yield();
            std::cerr << "C couldn't decide which to buy, so gave up.\n";
        }
    };
    
    
    int main() {
        std::cerr << "So, this is what happened.\n";
        A a;
        B b;
        C c;
        for (size_t i=0; i<10; ++i) {
            a();
            b();
            c();
        }
        std::cerr << "Then it all was done.\n";
    }
    

    Then compiling and running looks like this:

    $ g++ -std=c++11 -o coroutines coroutines.c++ -lboost_context
    $ ./coroutines
    So, this is what happened.
    A went to the store one day.
    B went to the store one day.
    C went to the store one day.
    A was looking for groceries.
    B was looking for replacement tires.
    C was looking for USB drives.
    A finally found what she was looking for.
    B didn't find anything at all.
    C found several with competitive pricing.
    B went to another store.
    C couldn't decide which to buy, so gave up.
    B got the tires installed there.
    Then it all was done.