読者です 読者をやめる 読者になる 読者になる

Boost.Context 再始動

C++

Boost.Contextにstart()という関数がありますが、これは再始動には使えないみたいです。
再始動する場合には、contextを作り直す必要があります。contextクラスはムーブ代入演算子を持ってるので、コンストラクトした一時オブジェクトの所有権を移譲することで作り直しができます。

#include <iostream>
#include <boost/context/all.hpp>
#include <boost/function.hpp>
#include <boost/utility/value_init.hpp>

class continuation {
    boost::contexts::context ctx_;
    boost::function<void(continuation&)> fn_;
    boost::initialized<bool> started_;

    void trampoline_()
    { fn_(*this); }

public:
    continuation(boost::function<void(continuation&)> const& fn)
    {
        ctx_ = boost::contexts::context(
                    &continuation::trampoline_,
                    this,
                    boost::contexts::default_stacksize(),
                    boost::contexts::stack_unwind,
                    boost::contexts::return_to_caller);

        fn_ = fn;
    }

    int start()
    { return ctx_.start(); }

    int resume()
    { return ctx_.resume(); }

    int restart()
    {
        ctx_ = boost::contexts::context(
                    &continuation::trampoline_,
                    this,
                    boost::contexts::default_stacksize(),
                    boost::contexts::stack_unwind,
                    boost::contexts::return_to_caller);
        return start();
    }

    int suspend(int vp)
    { return ctx_.suspend(vp); }

    bool is_complete() const
    { return ctx_.is_complete(); }
};

void f(continuation& cont)
{
    cont.suspend(1);
    cont.suspend(2);
    cont.suspend(3);
}

int main()
{
    continuation cont(f);

    std::cout << cont.start() << std::endl;
    std::cout << cont.resume() << std::endl;
    std::cout << cont.resume() << std::endl;
    cont.resume();

    // assert(!is_started() && !is_complete())に引っかかる
//  std::cout << cont.start() << std::endl;

    std::cout << cont.restart() << std::endl;
    std::cout << cont.resume() << std::endl;
    std::cout << cont.resume() << std::endl;
}
1
2
3
1
2
3