Производитель / Потребитель, использующий Boost.Fibers
Я пытаюсь создать производителя / потребителя, используя 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: в экземпляре статической пустоты 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:: integra_constant] ': /usr/include/c++/7/bits/std_function.h:227:16: требуется от' static bool std:: _ Function_base:: _ Base_manager<_Functor>:: _ M_manager (std:: _ Any_data &, const std:: _ Any_data &, std:: _ Manager_operation) [с _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 = 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::submit()::::(const fiber_worker::submit()::&) 'new _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:: fibres:: Promise:: Promise(Const Boost:: fiber:: 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: похоже, что канал не может использовать движущиеся лямбды
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:: волокна для уточнения
EDIT002: нет проблем с boost::fibers::buffered_channel
единственная проблема здесь с моим болезнью Альцгеймера, я (снова) забыл, что std::function
должен быть копируемым, а когда лямбда захватывает только подвижный тип std::function
создание не удастся при копировании
0 ответов
Я считаю, что проблема не в том, что небуферизованный канал не может передавать подвижные элементы (одна из перегрузок push принимает T&&), а в том, что он требует, чтобы они были сконструированы по умолчанию, чтобы он мог предварительно заполнить очередь элементами для переместите перемещаемый элемент в.