2008-09-17 8 views

ответ

15

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

+0

Функция обертки должна иметь C-связь. Функциональные указатели свободных функций могут быть несовместимы из-за языковой привязки – sellibitze 2010-06-22 06:52:37

11

Вы должны инициализировать ее, используя пустоту * параметр:

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);
+0

Спасибо за это, поскольку я исследую свой текущий pthread в C++-проблеме. Однако разве это не конфликтует с ответом, расположенным здесь: http://stackoverflow.com/questions/592160/static-vs-extern-c. Вам не нужно добавлять extern «C» каким-то образом? Кроме того, есть ли проблема с выполнением фактической работы в StaticThreadProc? – 2013-06-18 19:17:35

23

Это можно просто сделать с помощью библиотеки повысить, например:

#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 в исходный файл, где вы запускаете поток. Если вы только начинаете с повышения, все остальное из этого большого и устрашающего пакета можно игнорировать.

В C++ 11 вы можете сделать то же самое, но без повышения

// 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 
+0

Итак, я не против этого ... но никто в магазине, в котором я работаю, использует boost ...это будет большой сдвиг парадигмы. Его довольно огромная библиотека, а также ... как лучше всего начать ее использовать? – jdt141 2008-09-17 19:38:30

+0

Ну, на самом деле это не библиотека вообще, просто куча включений. Таким образом, вы можете выбрать небольшую часть этого, которая ловит вашу фантазию и начинать, включая те заголовки, в которых они вам нужны. Просто пара опрятных новых функций языка, которые вы можете использовать здесь и там, как представляется, уместным. – ravenspoint 2008-09-19 02:02:19

3

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

BOOST - это C++, поскольку CPAN предназначен для Perl. :)

0

Библиотека ускорения предоставляет механизм копирования, который помогает передавать информацию об объекте в новую тему. В другом примере 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 

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