Инкапсулировать функцию потока с помощью boost bind

#c #boost #boost-thread #boost-bind

#c #boost #boost-поток #boost-привязка

Вопрос:

В настоящее время я создаю boost::threads следующим образом:

   boost::thread m_myThread; //member variable
  //...
  m_myThread = boost::thread(boost::bind(amp;MyClass::myThreadFunction, this));
  

Это запустит поток, который выполняет функцию-член «myThreadFunction».

Я хотел бы инкапсулировать запуск нового потока и использовать что-то вроде

 boost::thread m_myThread; //member variable
//...
startAThread(amp;m_myThread, boost::bind(amp;MyClass::myThreadFunction, this), 123 /*some int argument*/);
  

Я думал, что смогу реализовать «startAThread» следующим образом:

 namespace internal
{
    template <typename Callable>
    void threadhelper(Callable func, int x)
    {
        doSomething(x);
        func();
    }
}
template <typename Callable>
void startAThread(boost::thread* threadToCreate, Callable func, int x)
{

    *threadToCreate = boost::thread(boost::bind(internal::threadhelper<Callable>, func, x));
}
  

Однако это не удается скомпилировать с

 usr/include/boost/bind/bind.hpp: In member function 'void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, Famp;, Aamp;, int) [with F = void (*)(boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, int), A = boost::_bi::list0, A1 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, A2 = boost::_bi::value<int>]':
usr/include/boost/bind/bind_template.hpp:20:   instantiated from 'typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = void (*)(boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, int), L = boost::_bi::list2<boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, boost::_bi::value<int> >]'
usr/include/boost/thread/detail/thread.hpp:61:   instantiated from 'void boost::detail::thread_data<F>::run() [with F = boost::_bi::bind_t<void, void (*)(boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, int), boost::_bi::list2<boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, boost::_bi::value<int> > >]'
MyClass.cpp:160:   instantiated from here
usr/include/boost/bind/bind.hpp:313: error: conversion from 'void' to non-scalar type 'boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >' requested
  

Что означает эта ошибка? Что не так с кодом?

Большое спасибо!

Комментарии:

1. Вы также должны добавить вызов createThreadWithPriority (или это вызов startAThread выше?) — Простая ошибка заключается в том, что вы не func переходите от createThreadWithPriority к internal::threadhelper .

2. конечно, вы правы. Это были две ошибки, допущенные при подготовке кода для публикации. Теперь он должен соответствовать коду, который у меня действительно есть.

3. Если вы спрашиваете о возникшей у вас проблеме с компилятором, вы всегда должны публиковать код, который воспроизводит проблему, и стараться как можно больше помогать другим в чтении сообщений об ошибках. В частности, в коде нет указания на то, где MyClass.cpp строка 160 есть. (Я предполагаю, что перед теми, на которые вы указываете, ошибок нет). Я не знаю, можно ли даже с этой информацией легко ответить на этот вопрос, поэтому я бы попытался создать тест, максимально похожий на ваш код, и добиться его сбоя таким же образом (начните с удаления boost::thread из уравнения).

Ответ №1:

Попробуйте

 namespace internal
{
    template <typename Callable>
    void threadhelper(Callable func, int x)
    {
        doSomething(x);
        func();
    }
}
template <typename Callable>
void startAThread(boost::threadamp; threadToCreate, Callable func, int x) {        
    threadToCreate = boost::thread(boost::bind(amp;internal::threadhelper<Callable>, func, x));
}
  

Я также использовал ссылку вместо указателя.