【问题标题】:Producer/Consumer using Boost.Fibers使用 Boost.Fibers 的生产者/消费者
【发布时间】:2018-09-25 03:45:43
【问题描述】:

我正在尝试使用 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<_functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::false_type) [with _Functor = 纤维工人::提交()::; std::false_type = std::integral_constant]’: /usr/include/c++/7/bits/std_function.h:227:16: 需要来自‘static 布尔 std::_Function_base::_Base_manager<_functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Functor = Fiber_worker::submit()::]' /usr/include/c++/7/bits/std_function.h:695:19:需要从 'std::function<_res ...>::function(_Functor) [with _Functor = 纤维工人::提交()::; =无效; =无效; _Res = 无效; _ArgTypes = {}]' /home/user/Development/Tests/shared_state_test/main.cpp:45:66:
从这里需要/usr/include/c++/7/bits/std_function.h:192:6: 错误:使用已删除的功能 'fiber_worker::submit()::::(const Fiber_worker::submit()::&)’ 新 _Functor(__source._M_access<_functor>>()); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/user /Development/Tests/shared_state_test/main.cpp:45:36:注意: 'fiber_worker::submit()::::(const Fiber_worker::submit()::&)' 被隐式删除,因为 默认定义格式不正确: ch.push(p{std::move(prom)} 可变 { p.set_value(); }); ^ /home/user/Development/Tests/shared_state_test/main.cpp:45:36:错误: 使用已删除的函数‘boost::fibers::promise::promise(const boost::fibers::promise&)’ 在包含的文件中 /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: 注意:在这里声明 承诺(承诺 const&)= 删除; ^~~~~~~

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::fibers 维护人员进行澄清

EDIT002: boost::fibers::buffered_channel 没有问题,这是我的阿尔茨海默症的唯一问题,我(再次)忘记了 std::function 必须是可复制的,当 lambda 仅捕获可移动类型时,std::function 创建将在复制时失败

【问题讨论】:

  • 频道明确要求任务是可复制的。
  • 是的,已经想通了。我(再次)忘记了 std::function 必须是可复制和可复制的
  • @sehe, BTW, boost::fibers::unbuffered_channel 可以接受只能移动的实体,为什么 buffered 不能?特别是当buffered push 可以接受左值时?

标签: c++ boost boost-thread fiber


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多