// Interface C++ aux Thread POSIX - R. Ansari 02/2001 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #include "zthread.h" #include #include /*! \class SOPHYA::ZThread \ingroup SysTools This class provides an interface for creating and controlling threads. The implementation uses the POSIX thread interface. The ZThread objects can be sub classed with the redefinition of the \c run() method which then performs the task. The default \c run() method of the base class can be used directly to perform computation through a function (see \b setAction() method) \sa SOPHYA::ZMutex The following sample code shows the usage of ZThread object to run simultaneously to functions to perform computation. \code // The functions to perform computing void fun1(void *arg) { } void fun2(void *arg) { } // ... ZThread zt1; zt1.setAction(fun1, arg[1]); ZThread zt2; zt2.setAction(fun2, arg[1]); cout << " Starting threads ... " << endl; zt1.start(); zt2.start(); cout << " Waiting for threads to end ... " << endl; zt1.join(); zt2.join(); \endcode */ #define CheckSt(st_, strg_) if (st_ != 0) perror(strg_); /* extern "C" { void * zthr_run( void * xthr); } */ static void * zthr_run(void * xthr) { ZThread * thr = (ZThread *)xthr; thr->run(); pthread_exit(NULL); return NULL; } /* ------ Classe ZThread ------- */ /*! Constructor, with optional specification of the thread stack size. */ ZThread::ZThread(size_t stacksize) { _initok = false; _ssize = 0; _act = NULL; _usp = NULL; _rc = -99; } ZThread::~ZThread() { // Que faut-il faire ? } /*! Method which starts the thread. */ void ZThread::start() { if (_initok) throw ZThreadExc("ZThread::Start() - Already started thread !"); int rc; pthread_attr_t tha; rc = pthread_attr_init(&tha); CheckSt(rc,"ZThread::start() - Pb creating tha attribute object"); if (_ssize > 0) rc = pthread_attr_setstacksize(&tha, _ssize); rc = pthread_create(&_thr, &tha, zthr_run, this); CheckSt(rc,"ZThread::start() - Pb creating the thread object"); _initok = true; setRC(rc); } /*! Calls the pthread_cancel. Can be used to stop a running thread. */ void ZThread::cancel() { if (!_initok) throw ZThreadExc("ZThread::cancel() - thread not started !"); int rc = pthread_cancel(_thr); CheckSt(rc,"ZThread::cancel() - Pb pthread_cancel() "); setRC(-77); } /*! Waits for the thread to terminate. */ void ZThread::join() { if (!_initok) throw ZThreadExc("ZThread::join() - thread not started !"); void * x; int rc = pthread_join(_thr, &x); CheckSt(rc,"ZThread::Join() - Pb pthread_join() "); return; } /*! This virtual method can be redefined in the derived class, in order to perform the actual computation. */ void ZThread::run() { if (_act) _act(_usp); setRC(0); return; } /* ------ Classe ZMutex ------- */ /*! \class SOPHYA::ZMutex \ingroup SysTools This class implements an interface to the Mutual Exclusion objects of the POSIX threads. The ZMutex objects should be used to control acces from different threads to common objects through the \b lock() and \b unlock() methods. \sa SOPHYA::ZSync */ /*! Constructor: Creates a associated pair of POSIX \c pthread_mutex_t and \c pthread_cond_t objects */ ZMutex::ZMutex() { _mutx = new pthread_mutex_t; _condv = new pthread_cond_t; int rc; rc = pthread_mutex_init(_mutx, NULL); CheckSt(rc,"ZMutex::ZMutex() Pb pthread_mutex_init"); rc = pthread_cond_init(_condv, NULL); CheckSt(rc,"ZMutex::ZMutex() Pb pthread_cond_init"); } ZMutex::~ZMutex() { delete _mutx; delete _condv; } /*! \class SOPHYA::ZSync \ingroup SysTools This class can be used to insure that the execution of a given part of the code is synchronised, i.e. only a single thread goes through this at a given time. The constructor acquires a lock on given \b ZMutex object, which is released by the destructor. The ZSync object should then be instanciated at the beginning of the synchronised instruction bloc. \sa SOPHYA::ZMutex */