我发现很多次,解决你所要求的问题的方法,在我看来都太复杂了。例如,你必须定义新的类类型,链接库等等。因此,我决定写几行代码,让最终用户能够基本上“线程化”任何类的“void ::method(void)”。
当然,我实现的这个解决方案可以扩展、改进等等,所以,如果你需要更具体的方法或功能,请添加它们,并请好心通知我。
这里有三个文件展示了我所做的。
#ifndef MUTEXCONDITION_H_
#define MUTEXCONDITION_H_
#include <pthread.h>
#include <stdio.h>
class MutexCondition
{
private:
bool init() {
pthread_mutex_init(&m_mut, NULL);
pthread_cond_init(&m_con, NULL);
return true;
}
bool destroy() {
pthread_mutex_destroy(&m_mut);
pthread_cond_destroy(&m_con);
return true;
}
public:
pthread_mutex_t m_mut;
pthread_cond_t m_con;
MutexCondition() {
init();
}
virtual ~MutexCondition() {
destroy();
}
bool lock() {
pthread_mutex_lock(&m_mut);
return true;
}
bool unlock() {
pthread_mutex_unlock(&m_mut);
return true;
}
bool wait() {
lock();
pthread_cond_wait(&m_con, &m_mut);
unlock();
return true;
}
bool signal() {
pthread_cond_signal(&m_con);
return true;
}
};
#endif
// 封装了将方法线程化的所有工作的类(test.h):
#ifndef __THREAD_HANDLER___
#define __THREAD_HANDLER___
#include <pthread.h>
#include <vector>
#include <iostream>
#include "Mutex.h"
using namespace std;
template <class T>
class CThreadInfo
{
public:
typedef void (T::*MHT_PTR) (void);
vector<MHT_PTR> _threaded_methods;
vector<bool> _status_flags;
T *_data;
MutexCondition _mutex;
int _idx;
bool _status;
CThreadInfo(T* p1):_data(p1), _idx(0) {}
void setThreadedMethods(vector<MHT_PTR> & pThreadedMethods)
{
_threaded_methods = pThreadedMethods;
_status_flags.resize(_threaded_methods.size(), false);
}
};
template <class T>
class CSThread {
protected:
typedef void (T::*MHT_PTR) (void);
vector<MHT_PTR> _threaded_methods;
vector<string> _thread_labels;
MHT_PTR _stop_f_pt;
vector<T*> _elements;
vector<T*> _performDelete;
vector<CThreadInfo<T>*> _threadlds;
vector<pthread_t*> _threads;
int _totalRunningThreads;
static void * gencker_(void * pArg)
{
CThreadInfo<T>* vArg = (CThreadInfo<T> *) pArg;
vArg->_mutex.lock();
int vIndex = vArg->_idx++;
vArg->_mutex.unlock();
vArg->_status_flags[vIndex]=true;
MHT_PTR mhtCalledOne = vArg->_threaded_methods[vIndex];
(vArg->_data->*mhtCalledOne)();
vArg->_status_flags[vIndex]=false;
return NULL;
}
public:
CSThread ():_stop_f_pt(NULL), _totalRunningThreads(0) {}
~CSThread()
{
for (int i=_threads.size() -1; i >= 0; --i)
pthread_detach(*_threads[i]);
for (int i=_threadlds.size() -1; i >= 0; --i)
delete _threadlds[i];
for (int i=_elements.size() -1; i >= 0; --i)
if (find (_performDelete.begin(), _performDelete.end(), _elements[i]) != _performDelete.end())
delete _elements[i];
}
int runningThreadsCount(void) {return _totalRunningThreads;}
int elementsCount() {return _elements.size();}
void addThread (MHT_PTR p, string pLabel="") { _threaded_methods.push_back(p); _thread_labels.push_back(pLabel);}
void clearThreadedMethods() { _threaded_methods.clear(); }
void getThreadedMethodsCount() { return _threaded_methods.size(); }
void addStopMethod(MHT_PTR p) { _stop_f_pt = p; }
string getStatusStr(unsigned int _elementIndex, unsigned int pMethodIndex)
{
char ch[99];
if (getStatus(_elementIndex, pMethodIndex) == true)
sprintf (ch, "[%s] - TRUE\n", _thread_labels[pMethodIndex].c_str());
else
sprintf (ch, "[%s] - FALSE\n", _thread_labels[pMethodIndex].c_str());
return ch;
}
bool getStatus(unsigned int _elementIndex, unsigned int pMethodIndex)
{
if (_elementIndex > _elements.size()) return false;
return _threadlds[_elementIndex]->_status_flags[pMethodIndex];
}
bool run(unsigned int pIdx)
{
T * myElem = _elements[pIdx];
_threadlds.push_back(new CThreadInfo<T>(myElem));
_threadlds[_threadlds.size()-1]->setThreadedMethods(_threaded_methods);
int vStart = _threads.size();
for (int hhh=0; hhh<_threaded_methods.size(); ++hhh)
_threads.push_back(new pthread_t);
for (int currentCount =0; currentCount < _threaded_methods.size(); ++vStart, ++currentCount)
{
if (pthread_create(_threads[vStart], NULL, gencker_, (void*) _threadlds[_threadlds.size()-1]) != 0)
{
return false;
}
else
{
++_totalRunningThreads;
}
}
return true;
}
bool run()
{
for (int vI = 0; vI < _elements.size(); ++vI)
if (run(vI) == false) return false;
return true;
}
T * addElement(void)
{
int vId=-1;
return addElement(vId);
}
T * addElement(int & pIdx)
{
T * myElem = new T();
_elements.push_back(myElem);
pIdx = _elements.size()-1;
_performDelete.push_back(myElem);
return _elements[pIdx];
}
T * addElement(T *pElem)
{
int vId=-1;
return addElement(pElem, vId);
}
T * addElement(T *pElem, int & pIdx)
{
_elements.push_back(pElem);
pIdx = _elements.size()-1;
return pElem;
}
T * getElement(int pId) { return _elements[pId]; }
void stopThread(int i)
{
if (_stop_f_pt != NULL)
{
( _elements[i]->*_stop_f_pt)() ;
}
pthread_detach(*_threads[i]);
--_totalRunningThreads;
}
void stopAll()
{
if (_stop_f_pt != NULL)
for (int i=0; i<_elements.size(); ++i)
{
( _elements[i]->*_stop_f_pt)() ;
}
_totalRunningThreads=0;
}
};
#endif
//一个用法示例文件“test.cc”,在Linux上我已经编译并使用了
封装所有线程化方法工作的类:
g++ -o mytest.exe test.cc -I. -lpthread -lstdc++
#include <test.h>
#include <vector>
#include <iostream>
#include <Mutex.h>
using namespace std;
class TPuck
{
public:
bool _go;
TPuck(int pVal):_go(true)
{
Value = pVal;
}
TPuck():_go(true)
{
}
int Value;
int vc;
void setValue(int p){Value = p; }
void super()
{
while (_go)
{
cout <<"super " << vc << endl;
sleep(2);
}
cout <<"end of super " << vc << endl;
}
void vusss()
{
while (_go)
{
cout <<"vusss " << vc << endl;
sleep(2);
}
cout <<"end of vusss " << vc << endl;
}
void fazz()
{
static int vcount =0;
vc = vcount++;
cout <<"Puck create instance: " << vc << endl;
while (_go)
{
cout <<"fazz " << vc << endl;
sleep(2);
}
cout <<"Completed TPuck..fazz instance "<< vc << endl;
}
void stop()
{
_go=false;
cout << endl << "Stopping TPuck...." << vc << endl;
}
};
int main(int argc, char* argv[])
{
int vN = 3;
CSThread<TPuck> PuckThreadMaker;
PuckThreadMaker.addThread(&TPuck::fazz, "fazz1");
PuckThreadMaker.addThread(&TPuck::fazz, "fazz2");
PuckThreadMaker.addThread(&TPuck::fazz, "fazz3");
PuckThreadMaker.addThread(&TPuck::vusss, "vusss");
PuckThreadMaker.addThread(&TPuck::super, "super");
PuckThreadMaker.addStopMethod(&TPuck::stop);
for (int ii=0; ii<vN; ++ii)
{
TPuck * vOne = PuckThreadMaker.addElement();
}
if (PuckThreadMaker.run() == true)
{
cout <<"All running!" << endl;
}
else
{
cout <<"Error: not all threads running!" << endl;
}
sleep(1);
cout <<"Totale threads creati: " << PuckThreadMaker.runningThreadsCount() << endl;
for (unsigned int ii=0; ii<vN; ++ii)
{
unsigned int kk=0;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
}
sleep(2);
PuckThreadMaker.stopAll();
cout <<"\n\nAfter the stop!!!!" << endl;
sleep(2);
for (int ii=0; ii<vN; ++ii)
{
int kk=0;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
}
sleep(5);
return 0;
}
pthread_create(&this->thread, NULL, this->functionPointer, NULL);
。这里的functionPointer
是一个类成员,并且在每个对象实例化时将指向普通函数的指针分配给该指针。然后它作为参数传递给pthread_create
,并作为this->functionPointer
。令人惊讶的是,它确实起作用。您可以在此处查看代码:[link]http://paste.ofcode.org/ETKUd2LS8XejYtskmDwBeu。您说`pthread_create`不知道`this`是什么。那么,您能解释一下这里的`this`是如何工作的吗? - RohitthreadOne()
从未尝试使用其参数args
。如果它这样做,它将得到NULL
,并且无法访问Thread
对象实例。那里有什么令人惊讶的? - Adam Rosenfield