使用Boost.Fibers的制作人/消费者

时间:2018-04-15 08:03:18

标签: c++ boost boost-thread fiber

我正在尝试使用Boost.Fibers创建生产者/消费者。看起来使用此example中的channels是正确的做法。由于我想使用promise/future表示完成,因此必须略微更改示例。所以我写了一些天真的代码,不做任何工作,只是表示完成。

struct fiber_worker {
    fiber_worker() {
        wthread = std::thread([self{this}]() {
            for (int i = 0; i < 4; ++i) {
                boost::fibers::fiber{
                        [self]() {
                            task tsk;
                            while (boost::fibers::channel_op_status::closed != self->ch.pop(tsk)) {
                                tsk();
                            }
                        }}.detach();
            }
            task tsk;
            while (boost::fibers::channel_op_status::closed != self->ch.pop(tsk)) {
                tsk();
            }
        });
    }

    boost::fibers::future<void> submit() noexcept {
        boost::fibers::promise<void> prom;
        auto retVal = prom.get_future();
        ch.push([p{std::move(prom)}]() mutable { p.set_value(); });
        return retVal;
    }

    ~fiber_worker() {
        ch.close();
        wthread.join();
    }

    using task = std::function<void()>;
    std::thread wthread;
    boost::fibers::buffered_channel<task> ch{1024};
};

但是,它不会编译,它会抱怨正在访问的promise已删除的复制构造函数。首先,我没有得到复制构造函数被调用的地方(以及为什么)。其次,我不确定这是boost::fibers应该使用的方式 用法

int main() {
        fiber_worker bwk;
        bwk.submit().get();
}

错误消息

  

在/ usr / include / c ++ / 7 / future:48:0中包含的文件中,                    来自/home/user/Downloads/boost_1_66_0/boost/fiber/exceptions.hpp:12,                    来自/home/user/Downloads/boost_1_66_0/boost/fiber/future/future.hpp:17,                    来自/home/user/Development/Tests/shared_state_test/main.cpp:4:   /usr/include/c++/7/bits/std_function.h:实例化'静态   空虚   的std :: _ Function_base :: _ Base_manager&LT; _Functor&GT; :: _ M_clone(STD :: _ Any_data&安培;,   const std :: _ Any_data&amp;,std :: false_type)[with _Functor =   fiber_worker ::提交()::; std :: false_type =   的std :: integral_constant]”:   /usr/include/c++/7/bits/std_function.h:227:16:从'静态要求   布尔   的std :: _ Function_base :: _ Base_manager&LT; _Functor&GT; :: _ M_manager(STD :: _ Any_data&安培;,   const std :: _ Any_data&amp;,std :: _ Manager_operation)[with _Functor =   fiber_worker ::提交()::]”   /usr/include/c++/7/bits/std_function.h:695:19:需要   'std :: function&lt; _Res(_ArgTypes ...)&gt; :: function(_Functor)[with _Functor   = fiber_worker :: submit()::; =无效=无效_Res = void; _ArgTypes = {}]'   /home/user/Development/Tests/shared_state_test/main.cpp:45:66:
  从这里需要/usr/include/c++/7/bits/std_function.h:192:6:   错误:使用已删除的功能   “fiber_worker ::提交()::: :(常量   fiber_worker ::提交()::&安培;)”         new _Functor( __ source._M_access&lt; _Functor &gt;());         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ / home / user /Development/Tests/shared_state_test/main.cpp:45:36:注意:   “fiber_worker ::提交()::: :(常量   fiber_worker :: submit()::&amp;)'被隐式删除,因为   默认定义是不正确的:            ch.push(p {std :: move(prom)} mutable {p.set_value();});                                       ^ /home/user/Development/Tests/shared_state_test/main.cpp:45:36:错误:   使用已删除的函数'boost :: fibers :: promise :: promise(const   boost :: fibers :: promise&amp;)'包含在文件中   /home/user/Development/Tests/shared_state_test/main.cpp:5:0:   /home/user/Downloads/boost_1_66_0/boost/fiber/future/promise.hpp:192:5:   注意:在此声明        promise(promise const&amp;)= delete;        ^ ~~~~~~

EDIT001: 看起来该频道无法使用移动的lambdas

struct test {
    test() = default;

    test(const test &rhs) = delete;

    test &operator=(const test &rhs)= delete;

    test(test &&rhs) = default;

    test &operator=(test &&rhs)= default;

    size_t _1 = 0;
    size_t _2 = 0;
    size_t _3 = 0;
    size_t _4 = 0;

    void print() const {
        std::cout << _1 << _2 << _3 << 4 << std::endl;
    }
};

int main() {
    using task = std::function<void()>;
    boost::fibers::buffered_channel<task> ch{1024};
    test tst;
    ch.push([t{std::move(tst)}]() { t.print(); });
}

将联系boost :: fiber维护者进行澄清

EDIT002: boost::fibers::buffered_channel这是我的老年痴呆症唯一的问题没有问题,我(再次)忘记了std::function必须是可复制的,当lambda捕获只有可移动类型std::function时,创建将失败复制

1 个答案:

答案 0 :(得分:0)

我认为问题不在于未缓冲的通道不能传递可移动项(push的重载之一是T &&),而是要求它们是默认可构造的,以便它可以预先填充队列带有将推送的项目移入其中的元素。