Лучший способ начать поток как член класса С++?

Мне интересно, как начать pthread, который является членом класса С++? Мой собственный подход следует за ответом...

Ответ 1

Обычно я использую статическую функцию-член класса и использую указатель на класс как параметр void *. Эта функция может либо выполнить обработку потока, либо вызвать другую нестационарную функцию-член с ссылкой на класс. Эта функция может ссылаться на все члены класса без неудобного синтаксиса.

Ответ 2

Это можно просто сделать, используя библиотеку boost, например:

#include <boost/thread.hpp>

// define class to model or control a particular kind of widget
class cWidget
{
public:
void Run();
}

// construct an instance of the widget modeller or controller
cWidget theWidget;

// start new thread by invoking method run on theWidget instance

boost::thread* pThread = new boost::thread(
    &cWidget::Run,      // pointer to member function to execute in thread
    &theWidget);        // pointer to instance of class

Примечания:

  • Здесь используется обычная функция-член класса. Нет необходимости добавлять дополнительные статические элементы, которые путают ваш интерфейс класса.
  • Просто включите boost/thread.hpp в исходный файл, где вы запускаете поток. Если вы только начинаете с повышения, все остальное из этого большого и запугивающего пакета можно игнорировать.

В С++ 11 вы можете сделать то же самое, но без boost

// define class to model or control a particular kind of widget
class cWidget
{
public:
void Run();
}

// construct an instance of the widget modeller or controller
cWidget theWidget;

// start new thread by invoking method run on theWidget instance

std::thread * pThread = new std::thread(
    &cWidget::Run,      // pointer to member function to execute in thread
    &theWidget);        // pointer to instance of class

Ответ 3

Вы должны загрузить его с помощью параметра void *:

class A
{
  static void* StaticThreadProc(void *arg)
  {
    return reinterpret_cast<A*>(arg)->ThreadProc();
  }

  void* ThreadProc(void)
  {
    // do stuff
  }
};

...

pthread_t theThread;
pthread_create(&theThread, NULL, &A::StaticThreadProc, this);

Ответ 4

Я использовал три метода, описанных выше. Когда я впервые использовал потоки в С++, я использовал статические функции-члены, затем функции друга и, наконец, библиотеки BOOST. В настоящее время я предпочитаю BOOST. За последние несколько лет я стал настоящим фанатом BOOST.

BOOST - это С++, поскольку CPAN для Perl.:)

Ответ 5

Библиотека ускорения предоставляет механизм копирования, который помогает передавать информацию об объекте к новой теме. В другом примере boost boost:: bind будет скопирован с помощью указателя, который также просто скопирован. Поэтому вам придется позаботиться о действительности своего объекта, чтобы предотвратить свисающий указатель. Если вы реализуете оператор() и вместо него создаете конструктор копирования и передаете объект напрямую, вам не нужно его заботиться.

Более приятное решение, которое предотвращает много неприятностей:

#include <boost/thread.hpp>

class MyClass {
public:
        MyClass(int i);
        MyClass(const MyClass& myClass);  // Copy-Constructor
        void operator()() const;          // entry point for the new thread

        virtual void doSomething();       // Now you can use virtual functions

private:
        int i;                            // and also fields very easily
};

MyClass clazz(1);
// Passing the object directly will create a copy internally
// Now you don't have to worry about the validity of the clazz object above
// after starting the other thread
// The operator() will be executed for the new thread.
boost::thread thread(clazz);             // create the object on the stack

Другой пример boost создает объект потока в куче, хотя для этого нет смысла.