Najlepszy sposób na rozpoczęcie wątku jako członek klasy C++?

Zastanawiam się nad najlepszym sposobem na uruchomienie pthread, który jest członkiem klasy C++? Moje własne podejście jest odpowiedzią...

Author: jdt141, 2008-09-17

5 answers

Zwykle używam statycznej funkcji członka klasy i używam wskaźnika do klasy jako parametru void *. Ta funkcja może następnie albo wykonać przetwarzanie wątku, albo wywołać inną niestatyczną funkcję członka z referencją do klasy. Ta funkcja może wtedy odwoływać się do wszystkich członków klasy bez niewygodnej składni.

 15
Author: shmuelp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 18:27:15

Można to po prostu zrobić za pomocą biblioteki boost, jak to:

#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

Uwagi:

  • używa zwykłej funkcji członka klasy. Nie ma potrzeby dodawania dodatkowych, statycznych członków, które mylą interfejs klasy
  • wystarczy dodać boost/thread.hpp w pliku źródłowym, w którym rozpoczynasz wątek. Jeśli dopiero zaczynasz z boostem, cała reszta tego dużego i zastraszającego pakietu może zostać zignorowana.

W C++11 możesz zrobić to samo, ale bez 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
 23
Author: ravenspoint,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-08 15:14:40

Musisz go bootstrap używając parametru 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);
 11
Author: Adam Rosenfield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 19:04:29

Użyłem trzech z opisanych powyżej metod. Kiedy po raz pierwszy użyłem threadingu w c++ użyłem static member functions, następnie friend functionsi wreszcie BOOST libraries. Obecnie wolę BOOST. W ciągu ostatnich kilku lat stałem się wielkim BIGOTEM.

BOOST jest do C++ tak jak CPAN do Perla. :)

 3
Author: Thanatopsis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 20:28:55

Biblioteka boost zapewnia mechanizm kopiowania, który pomaga w przesyłaniu informacji o obiekcie do nowego wątku. W innym przykładzie boost:: bind zostanie skopiowane ze wskaźnikiem, który również jest po prostu skopiowany. Więc musisz zadbać o ważność obiektu, aby zapobiec zwisającemu wskaźnikowi. Jeśli zaimplementujesz operator () i zamiast tego dostarczysz Konstruktor kopiujący i przekażesz obiekt bezpośrednio, nie musisz się tym przejmować.

O wiele ładniejsze rozwiązanie, które zapobiega wielu "trouble": {]}
#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

Drugi przykład boost tworzy obiekt thread na stercie, chociaż nie ma sensu tego robić.

 0
Author: CSpille,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-12 17:37:35