2014-08-27 3 views
0

Так что я пытаюсь выяснить, можете ли вы использовать любопытно повторяющийся шаблон шаблона, чтобы обойти ограничения использования pthread с помощью методов класса и даже создания классов, делая что-то вроде этого.Любопытно повторяющийся шаблон с ptrhead

template <class T> 
class thread_helper 
{ 
    static void* create(void *input) 
    { 
    T * output=new T; 
    return static_cast<void*>(output); 
    } 

    static void* using(void *input) 
    { 
    T::use(input); 
    } 
}; 

class user : public thread_helper<user> 
{ 
    void method(int x) 
    { 
    //does something 
    } 
    static void use(void* input) 
    { 
    this->method(static_cast<int>(input)); 
    } 
}; 

Затем вы можете использовать PTHREAD назвать создание класса с использованием

pthread_create(thread_variable, NULL, thread_helper::create<some_class>, void); 

и для другого вызова

pthread_create(thread_variable, NULL, user::using(), void); 

примечание: Есть много ошибок в коде выше. Пожалуйста, не раздирайте меня. Я действительно просто пытаюсь нарисовать картину того, что я пытаюсь сделать. Я также пытаюсь выяснить, есть ли лучший способ сделать эту операцию.

Кроме того, второй метод pthread_create действительно необходим, я не могу использовать конструктор для этого тоже?

+0

Использование зарезервированного слова. Во всяком случае, типичная парадигма заключается в том, чтобы указать ваш экземпляр экземпляра класса void * и передать это как параметр потока для процедуры потока, которая возвращает его в качестве одного и того же указателя. Если у вас есть C++ 11, рассмотрите использование std :: thread. –

+0

«если есть лучший способ выполнить эту операцию» - запуск конструктора в отдельном потоке не всегда полезен, если у вас нет синхронизированного способа доступа к объекту после этого - я предлагаю вам прочитать ['std :: future '] (http://en.cppreference.com/w/cpp/thread/future) и др. –

+0

@TonyD Я проверил std :: future. Меня раздражает то, что я не могу использовать новый стандарт для этого проекта. Я также согласен с вами в том, что часть конструктора на самом деле не нужна. В любом случае, я получил код, который работает, и он работает, но его тонна кодовой таблички. –

ответ

0

Я собираюсь опубликовать рабочий тестовый код. Он включает тонну кода котельной плиты. Это действительно уродливый взгляд, но работает. Примечание. Вероятно, я изменил метод создания thread_helper позже, поэтому его нельзя использовать для потоковой передачи.

#include <iostream> 
#include "pthread.h" 

using namespace std; 

template <class I> 
struct helper 
{ 
    void *(I::*method)(void *); //enables you to call and get information from any non static class method 
    I *ptr; //this is the class pointer used to call the member pointer 
    void *info; //this is what you pass into the member pointer 
}; 

template <class T> 
class thread_helper 
{ 
public: 
    static void *create(void *in) 
    { 
     T * output=new T; 
     return static_cast<void*>(output); 
    } 

    static void *method(void *in) 
    { 
     helper<T> *utilize = static_cast<helper<T> *>(in); 
     return (utilize->ptr->*utilize->method)(utilize->info); 
    } 
}; 

class test: public thread_helper<test> 
{ 
public: 
    void *test_method(void *in) 
    { 
     int *val = (int *)in;//note: not static_casting since this is not a class 
     *val *= 4; 
     return val; //auto casts to void * 
    } 
}; 

int main() 
{ 
    //initialize test 
    test * second = static_cast<test*>(test::create(NULL)); 

    //initialize helper 
    helper<test> first; 
    first.ptr = second; 
    first.method = &test::test_method; 
    int val = 4; 
    first.info = &val;// 

    //setup threads 
    pthread_t thread; 
    void *ans; 

    //call test_method and retrieve answer 
    pthread_create(&thread, NULL, test::method, static_cast<void *>(&first)); 
    pthread_join(thread, &ans); 

    cout << "the answer is "<< *(int *)ans <<endl; 
    return 0; 
} 

Как было указано, это решение работает, если вы используете pthreads. И является общей заменой для записи функции или статического метода для вызова методов класса.

Если вы используете потоки boost или C++ 11, этот метод не нужен и, вероятно, не должен использоваться, так как для этого требуется много кода котельной плиты (литье указателя).

+0

Вы можете использовать 'reinterpret_cast' вместо C-cast. – Jarod42

+0

@ Jarod42 Не reinterpret_cast опасно? –

+0

C-Cast ** ** более опасен, потому что он не является явным. 'reinterpret_cast' является явным (но он по-прежнему опасен). – Jarod42

Смежные вопросы