【问题标题】:boost context class提升上下文类
【发布时间】:2012-07-27 19:31:32
【问题描述】:

我发现 boost 有一个叫 context 的类,用于上下文切换,对吧?

我尝试用谷歌搜索,但没有找到任何文档或示例。我只是想知道是否有人可以提供一些信息。

【问题讨论】:

    标签: c++ boost boost-context


    【解决方案1】:

    作者website 上的boost-coroutine 存档包含一些基于上下文的协程和上下文本身的基本文档和示例。您还可以在该网站上找到一个光纤包,至少作为另一个用例可能会很有趣。

    【讨论】:

    • 无赖。这个对我有用。请注意,包括基本示例和文档的上下文现在位于 boost 主干中。如果不想通过SVN结账,也可以在线浏览here。协程和纤程(还)不在主干中。
    • 顺便说一句,协程和光纤的积极开发似乎发生在 Oliver Kowalke 的 git repository
    【解决方案2】:

    Boost::Context 是 Boost 1.51.0 及更高版本的官方部分。有关它的信息,请参阅http://www.boost.org/doc/libs/1_51_0/libs/context/doc/html/index.html。不幸的是,文档与实现稍有不同,而且 SVN 中发生了一些变化,因此您需要稍微阅读头文件。

    这是我前几天写的一个例子,展示了 Boost::Context 使用 Boost 1.51.0+最新的 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";
    }
    

    然后编译运行是这样的:

    $ 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.
    

    【讨论】:

    • @Lucretiel 它是班级的成员,就在代码中:std::array&lt;intptr_t, 64*1024&gt; stack; =)
    • 哦。我完全没有看到滚动条
    • dispatch 方法中的while (true) .. 是干什么用的?
    • @Dfr 用于何时/如果您的协程结束其调用实现。
    • 这是一个很好的例子,谢谢……但是你知道为什么第三个参数需要切换上下文吗? (old_context_ptr,new_context,神秘的int_arg)
    【解决方案3】:

    感谢 wjl 提供的示例代码。它帮助我理解了 boost context 是如何工作的,以及 boost coroutine 是如何通过 boost context 实现的。但是你的代码没有按原样工作,所以我修改它以在 Windows 上编译。 (虽然没有检查它是否适用于 Linux)

    #include <iostream>
    #include <array>
    #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";
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-18
      • 2019-10-04
      • 2016-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      相关资源
      最近更新 更多