Bunu istediğini çözmenin yollarını birçok kez buldum, bence çok karmaşık. Örneğin, yeni sınıf türleri, bağlantı kitaplığı vb. Tanımlamalısınız. Bu yüzden, son kullanıcının temelde "void :: method (void)" olan her ne sınıf. Elbette uyguladığım bu çözüm genişletilebilir, geliştirilebilir vb. Bu nedenle, daha spesifik yöntemlere veya özelliklere ihtiyacınız varsa, bunları ekleyin ve lütfen beni döngüde tutmak için çok nazik olun.
İşte ne yaptığımı gösteren 3 dosya.
#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
// Bir yöntemi evrelendirmek için tüm çalışmayı kapsüle eden sınıf (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
// Linux üzerinde bir kullanım örneği dosyası "test.cc" ile derlediğim tüm işi bir yöntemi iş parçacığına dahil eden sınıf: 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;
}