0

我正在尝试使用 Boost.Fibers 创建生产者/消费者。看起来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:在 'static void 的实例化中std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::false_type) [with _Functor = fiber_worker::submit()::; std::false_type = std::integral_constant]': /usr/include/c++/7/bits/std_function.h:227:16: 来自'static bool std::_Function_base::_Base_manager<_Functor>::_M_manager( std::_Any_data&, 常量 std::_Any_data&, std:: _Manager_operation) [with _Functor = fiber_worker::submit()::]' /usr/include/c++/7/bits/std_function.h:695:19: 来自 'std::function<_Res(_ArgTypes ...) >::function(_Functor) [with _Functor = fiber_worker::submit()::; =无效;=无效;_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)} mutable { 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: 注意:此处声明 promise(承诺 const&) = 删除;^~~~~~~

EDIT001:看起来频道无法使用移动 lambda

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创建将在复制时失败

4

1 回答 1

0

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

于 2019-10-08T04:55:19.933 回答