LINUX.ORG.RU

C++ и pthread


0

0

Можно ли отправить метод класса в тред?

class A
{
public:
        void *DataBufferHandler(void* param)
        {
	
	       pthread_detach(pthread_self());
	       cout << "OK\n";
        }
};

int main()
{
   A classA;
   pthread_t pthread_id;
   pthread_create(&pthread_id, NULL, classA.DataBufferHandler, (void*)NULL);
}

При компиляции выдаёт вот это: ошибка: аргумент типа ‘void* (A::)(void*)’ не соответствует типу ‘void* (*)(void*)’

раньше вроде никогда так не делал, а теперь понадобилось. Куда копать?

Ну сколько можно....

В pthread_create указатель на метод класса передавать нельзя!

Метод класса можно запустить в треде. Просто сделай промежуточную вспомогательную функцию, и ей, аргументом, передавай this.

AF ★★★
()
Ответ на: Ну сколько можно.... от AF

>Просто сделай промежуточную вспомогательную функцию, и ей, аргументом, передавай this.

На самом деле тред будет запускаться из конструктора, поэтому такой метод мне не катит.

golodranez ★★★★
() автор топика

На RSDN-е подсказывают следующее:

template<class T, DWORD(T::*mem_fun)()>
inline
DWORD WINAPI thread_to_member_thunk(void* p)
{
     return (static_cast<T*>(p)->*mem_fun)();
}

struct some
{
     DWORD f() { return 0; }
};

int main()
{
     some s;
     // в качестве параметра (lpParam) передаем указатель на объект, чтобы переходник направил поток именно в этот объект
     CreateThread(0, 0, thread_to_member_thunk<some, &some::f>, &s, 0, 0);
}
one_more_hokum ★★★
()
Ответ на: комментарий от golodranez

Свой велосипед пишешь? Молодец :)

Я так понимаю, что у тебя базовый класс с виртуальным методом, который должен отщелкиваться в тред?

Посмотри на исходники QThread из Qt. Там то, что тебе нужно. Правда сам тред стартует не из конструктора, а по вызову спец. метода базового класса.

В принципе можно сделать пару отжиманий, приседаний и т д и запустить тред из конструктора (точнее добится вида - как будто из конструктора). Но на практике такое поведение тебе врядли понадобится.

AF ★★★
()
Ответ на: Свой велосипед пишешь? Молодец :) от AF

Ну да, не обязательно из конструктора - можно из любого метода класса.

Посмотри на исходники QThread из Qt.

Гляну завтра на работе.

golodranez ★★★★
() автор топика
Ответ на: комментарий от one_more_hokum

>На RSDN-е подсказывают следующее:

Тебя ничего не смущает в этом коде? :))

golodranez ★★★★
() автор топика
Ответ на: комментарий от Valeriy_Onuchin

объявляй static и передавай

static в смысле:

class A 
{ 
public: 
        static void *DataBufferHandler(void* param) 
        { 
    
          pthread_detach(pthread_self()); 
          cout << "OK\n"; 
        } 
};

Да?

PS блин, компилятора под рукой нет

golodranez ★★★★
() автор топика
Ответ на: комментарий от golodranez

На самом деле тред будет запускаться из конструктора, поэтому такой метод мне не катит.

Это отчасти порочная практика. А если pthread_create() вернет ошибку? Как ты о ней будешь сообщать вызывающему коду? Бросать исключение? А если он этого не хочет но хочет обрабатывать ошибки не прибегая к исключениям?

bibi
()
Ответ на: комментарий от LamerOk

довольно стандартный метод:

class A
{
private:
   virtual void ThreadProc() {
        cout << "OK\n";
        pthread_detach(pthread_self());
   }
public:
    static void *ThreadStub(void* param)
   {
       A *classA = (A*)param;
      classA->ThreadProc();
   }
};

int main()
{
   A classA;
   pthread_t pthread_id;
   pthread_create(&pthread_id, NULL, A::ThreadStub, (void*)&classA);
} 

Valeriy_Onuchin ★★
()
Ответ на: комментарий от Valeriy_Onuchin
private: 
   virtual void ThreadProc() { 
        cout << "OK\n"; 
        pthread_detach(pthread_self()); 
   } 
public: 
    static void *ThreadStub(void* param) 
   { 
       A *classA = (A*)param; 
      classA->ThreadProc(); 
   } 

Я только не пойму зачем так делать(передавать this в тред, где потом запускать его метод), если вот так работает?

class A  
{  
public:  
        static void *DataBufferHandler(void* param)  
        {  
     
          pthread_detach(pthread_self());  
          cout << "OK\n";  
        }  
};
int main()
{
   A classA;
   pthread_t pthread_id; 
   pthread_create(&pthread_id, NULL, classA.DataBufferHandler, (void*)NULL); 

}

В чём тут прикол?

golodranez ★★★★
() автор топика
Ответ на: комментарий от golodranez

> pthread_create(&pthread_id, NULL, classA.DataBufferHandler, (void*)NULL);

Лучше всётаки вот так конечно - pthread_create(&pthread_id, NULL, A::DataBufferHandler, (void*)NULL);

golodranez ★★★★
() автор топика
Ответ на: комментарий от golodranez

>Я только не пойму зачем так делать(передавать this в тред, где потом запускать его метод), если вот так работает?

Чтобы иметь доступ к переменным экземпляра класса и вызывать нестатические методы.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

>Чтобы иметь доступ к переменным экземпляра класса и вызывать нестатические методы.

Угу, туплю:))

golodranez ★★★★
() автор топика
Ответ на: комментарий от golodranez

а что, конструктор теперь вызывается до выделения памяти объекту?

xydo ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.