Здесь я написал обертку потока для функции потока c pthread_create()
. Он позволит вызывать любой метод для любого объекта и передавать любое количество аргументов этому методу. API является:Общая функция обертки потока c для C++
template <typename T, typename R, typename... ATs>
pthread_t NewThread(T *obj, R (T::*mem)(ATs...), ATs... args);
Ниже приведен шаблон:
template<unsigned int i>
class TupleUnpack
{
public:
template<typename R, typename ...ATs, typename ...T_function_arguments>
inline static R unpack (R (*function) (ATs...),
std::tuple<ATs...> arguments_tuple,
T_function_arguments ...function_arguments)
{
return TupleUnpack<i-1>::unpack (function, arguments_tuple, std::get<i-1> (arguments_tuple), function_arguments...);
}
};
template<>
class TupleUnpack<0>
{
public:
template<typename R, typename ...ATs, typename ...T_function_arguments>
inline static R unpack (R (*function) (ATs...),
std::tuple<ATs...> arguments_tuple,
T_function_arguments ...function_arguments)
{
return function (function_arguments...);
}
};
class CallCaller
{
virtual bool dispatch (void)=0;
};
template<typename T,typename R,typename ...ATs>
class Call : public CallCaller
{
public:
Call (T *obj,R (*function) (ATs...),ATs... arguments) :obj(obj),function (function),tuplearg (arguments...) {}
~Call() {}
bool dispatch (void)
{
return TupleUnpack<sizeof ...(ATs)>::unpack (this->function, this->tuplearg);
}
private:
std::tuple<ATs...> tuplearg;
R (*function) (ATs...);
T *obj;
};
void *test(int d,double sf)
{
std::cout<<"yay my thread runs d="<<d<<" sf="<<sf<<std::endl;
}
template<typename T,typename R,typename ...ATs>
void* stub (void* vp)
{
Call<T,R,ATs...>* call = static_cast<Call<T,R,ATs...>*>(vp);
call->dispatch();
delete call;
pthread_exit (0);
}
template <typename T, typename R, typename... ATs>
pthread_t NewThread(T *ob, R (T::*mem)(ATs...), ATs... args)
{
pthread_t tid;
R (*func) (ATs...);
Call<T,R,ATs...> *task=new Call<T,R,ATs...>(ob,&test,args...);
pthread_create(&tid, nullptr, stub<T,R,ATs...>, task) ;
return tid;
}
Ниже файл CPP:
#include <tr1/tuple>
#include <utility>
#include <iostream>
#include <pthread.h>
#include <tuple>
#include <type_traits>
#include <utility>
#include "NewThread.hpp"
class X
{
public:
void *method(int a, double x)
{
std::cout<<"yay my tread runs a="<<a<<" x="<<x<<std::endl;
}
};
int main()
{
X x;
int i;
pthread_t tid = NewThread(&x, &X::method, 1234, 3.14);
pthread_join(tid,NULL);
std::cout<<"Thread Ended "<<tid<<std::endl;
return 0;
}
Я пытаюсь вызвать x::method()
с аргументами. Как вы можете видеть, у меня есть функция test()
, которая похожа на x::method()
, чтобы продемонстрировать, что мой поток работает. Но я хочу иметь возможность позвонить x::method()
. Может ли кто-нибудь направить меня?
В сущности мой выходной ток:
yay my thread runs d=1234 sf=3.14
Thread Ended 139766222432000
Я хочу, чтобы мой выход будет
yay my thread runs a=1234 x=3.14
Thread Ended 139766222432000
почему не используется [увеличить :: нить] (http://www.boost.org/libs/thread) и упростить вашу жизнь? – user2348816
@ user2348816 Я не могу использовать внешние библиотеки, кроме стандартной библиотеки и библиотеки шаблонов, которая поставляется с C++ 11. Это для класса C++, который я делаю – footy
Является ли заданием создать оболочку? Потому что теперь есть [std :: thread] (http://en.cppreference.com/w/cpp/thread/thread). – Collin