Hi All,
I am writting a Thread class with using pthread library. I have some
problem in saving thread function type and argument type. How to make
Thread class generic ?
Firstly take a look at boost::threads - it is pretty simple and small
;)
If you want to create another class for pthread do not forgot the next:
thread function (function passed to pthread_create) must have C
linkage, so it cannot be class/structure member.
Do not forget that it returns void* and takes void* as parameter, so
you should be careful with type conversion;)
As example it could be code below. Do not forget add correct error
handling. I hope it will be helpful ;)
//! Abstract class for thread execution.
class worker
{
public:
//! This method called in thread
virtual void execute() throw() = 0;
//! This method called when thread is canceled
virtual void cancel() throw() = 0;
//! this method called if error occur in thread
virtual void err_handle() throw()= 0;
//! Destructor.
virtual ~worker()
{}
};
extern "C" void* executor(void* b);
//! Main class for thread operations.
class thread
{
friend void* executor(void* b);
//! Main thread function.
//! \arg thread data.
//! \return thread result.
private:
//! disabled constructor
thread();
//! disabled constructor
thread(const thread& t);
//! disabled operator
thread& operator=(const thread& t);
public:
//! Constructor.
/*! Takes a pointer to worker object, and use it as
* thread function.
* \note In this case default thread attribute will be used.
*/
thread(worker* w)
: funct(w)
{
int r;
if ((r = pthread_attr_init(&attr)) != 0)
{
throw r;
}
}
//! Constructor.
//! \arg worker* w - worker object.
//! \arg const pthread_attr_t &attr_ - thread attribute.
thread(worker* w, const pthread_attr_t &attr_)
: attr(attr_), funct(w)
{ }
//! Destructor.
/*! Firstly thread is detached, and then it canceled.
* This approach is used because POSIX does not have other
approach
* to destroy other thread.
*/
virtual ~thread()
{
pthread_detach(tid);
pthread_cancel(tid);
}
//! Returns thread identifier (TID)
pthread_t getTID() const
{
return tid;
}
//! Returns TID of the thread in which this method called.
static pthread_t self()
{
return pthread_self();
}
//! Create new thread and returns it's TID.
//! \note In case of error exception with error code will be thrown
pthread_t create()
{
int r = pthread_create(&tid, &attr, executor, this);
if (r != 0)
{
throw r;
}
return tid;
}
//! Joins the thread. Thsi thread should be joinable.
//! \note In case of error exception with error code will be thrown
void join()
{
int r;
if ((r = pthread_join(tid, NULL)) != 0)
{
throw r;
}
}
//! Detaches the thread.
//! \note In case of error exception with error code will be thrown
void detach()
{
int r;
if ((r = pthread_detach(tid)) != 0)
{
throw r;
}
}
//! Detaches the thread which TID is tid_
//! \note In case of error exception with error code will be thrown
static void detach(pthread_t tid_)
{
int r;
if ((r = pthread_detach(tid_)) != 0)
{
throw r;
}
}
//! Cancels the thread.
//! \note In case of error exception with error code will be thrown
void cancel()
{
int r;
if ((r = pthread_cancel(tid)) != 0)
{
throw r;
}
}
//! Cancels the thread which TID is tid_.
//! \note In case of error exception with error code will be thrown
static void cancel(pthread_t tid_)
{
int r;
if ((r = pthread_cancel(tid_)) != 0)
{
throw r;
}
}
private:
pthread_t tid; //!< Thread's ID
pthread_attr_t attr;//!< Thread's attribute
worker* funct;//!< Thread's class function.
};
void* executor(void* b)
{
try{
thread *thr = reinterpret_cast<thread*>(b);
if (thr != NULL)
{
try
{
thr->funct->execute();
}catch(...)
{
thr->funct->err_handle();
}
}
}catch(...)
{}
return NULL;
}