source: Sophya/trunk/SophyaLib/SysTools/zthread.cc@ 3670

Last change on this file since 3670 was 3619, checked in by cmv, 16 years ago

add various #include<> for g++ 4.3 (jaunty 9.04), cmv 05/05/2009

File size: 6.5 KB
Line 
1// Interface C++ aux Thread POSIX - R. Ansari 02/2001
2// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
3
4#include "sopnamsp.h"
5#include "zthread.h"
6#include <stdlib.h>
7#include <stdio.h>
8#include <string.h>
9#include <pthread.h>
10#include <signal.h>
11
12/*!
13 \class SOPHYA::ZThread
14 \ingroup SysTools
15 \brief Simple class for creating and controlling threads.
16
17 This class provides an interface for creating and controlling threads.
18 The implementation uses the POSIX thread interface.
19 The ZThread objects can be sub classed with the redefinition of
20 the \c run() method which then performs the task.
21 The default \c run() method of the base class can be used directly
22 to perform computation through a function (see \b setAction() method)
23 \sa SOPHYA::ZMutex
24 The following sample code shows the usage of ZThread object
25 to run simultaneously two functions to perform computation.
26
27 \code
28 // The functions to perform computing
29 void fun1(void *arg) { }
30 void fun2(void *arg) { }
31 // ...
32 ZThread zt1;
33 zt1.setAction(fun1, arg[1]);
34 ZThread zt2;
35 zt2.setAction(fun2, arg[1]);
36 cout << " Starting threads ... " << endl;
37 zt1.start();
38 zt2.start();
39 cout << " Waiting for threads to end ... " << endl;
40 zt1.join();
41 zt2.join();
42 \endcode
43*/
44
45#define CheckSt(st_, strg_) if (st_ != 0) perror(strg_);
46
47/*
48extern "C" {
49 void * zthr_run( void * xthr);
50 void zthr_sig_exit(int s);
51}
52*/
53
54static int _RCR_ = 99;
55static void * zthr_run(void * xthr)
56{
57 ZThread * thr = (ZThread *)xthr;
58 thr->run_p();
59 return &_RCR_;
60}
61
62static void zthr_cleanup(void * xthr)
63{
64 ZThread * thr = (ZThread *)xthr;
65 if(thr->_status == 1) thr->_status = 2;
66 return;
67}
68
69static int _RCS_ = 97;
70static void zthr_sig_exit(int s)
71{
72 printf("zthr_sig_exit(int s=%d) signal received -> pthread_exit()\n",s);
73 pthread_exit(&_RCS_);
74}
75
76/* ------ Classe ZThread ------- */
77/*!
78 Constructor, with optional specification of the thread stack size.
79*/
80ZThread::ZThread(size_t stacksize)
81{
82 _status = 0;
83 _ssize = 0;
84 _act = NULL;
85 _usp = NULL;
86 _rc = -99;
87}
88
89ZThread::~ZThread()
90{
91 // Que faut-il faire ?
92}
93
94/*!
95 Method which starts the thread.
96*/
97void ZThread::start()
98{
99 if ( IfStarted() ) throw ZThreadExc("ZThread::Start() - Already started thread !");
100 int rc;
101 pthread_attr_t tha;
102 rc = pthread_attr_init(&tha);
103 CheckSt(rc,"ZThread::start() - Pb creating tha attribute object");
104 if (_ssize > 0)
105 rc = pthread_attr_setstacksize(&tha, _ssize);
106 rc = pthread_create(&_thr, &tha, zthr_run, this);
107 CheckSt(rc,"ZThread::start() - Pb creating the thread object");
108 setRC(rc);
109}
110
111/*!
112 Calls the pthread_cancel. Can be used to stop a running thread.
113*/
114void ZThread::cancel()
115{
116 if ( !IfStarted() ) throw ZThreadExc("ZThread::cancel() - thread not started !");
117 int rc = pthread_cancel(_thr);
118 CheckSt(rc,"ZThread::cancel() - Pb pthread_cancel() ");
119 setRC(-77);
120}
121
122/*!
123 Calls the pthread_kill to deliver a signal to the corresponding thread
124*/
125void ZThread::kill(int sig)
126{
127 if ( !IfStarted() ) throw ZThreadExc("ZThread::kill() - thread not started !");
128 int rc = pthread_kill(_thr, sig);
129 CheckSt(rc,"ZThread::kill() - Pb pthread_kill() ");
130 setRC(-76);
131}
132
133
134/*!
135 \brief Waits for the thread to terminate (call pthread_join() )
136*/
137void ZThread::join()
138{
139 if ( !IfStarted() ) throw ZThreadExc("ZThread::join() - thread not started !");
140 void * x;
141 int rc = pthread_join(_thr, &x);
142 CheckSt(rc,"ZThread::Join() - Pb pthread_join() ");
143 return;
144}
145
146/*!
147 \brief Method which does the actual computation
148 This virtual method can be redefined in the derived class, in order
149 to perform the actual computation. The default implementation call
150 the action function (if defined by setAction() )
151
152*/
153void ZThread::run()
154{
155 if (_act) _act(_usp);
156 setRC(0);
157 return;
158}
159
160/*!
161 \brief Method called by the function passed to pthread_create().
162 This method sets the clean-up handler, changes the status variable
163 and call the run() method, and pthread_exit() at the end.
164*/
165void ZThread::run_p()
166{
167 _status = 1;
168 pthread_cleanup_push(zthr_cleanup, (void *)this);
169 run();
170 _status = 2;
171 pthread_exit(&(_rc));
172 pthread_cleanup_pop(0);
173 return;
174}
175
176
177void ZThread::ActivateExitOnSignal(int sig)
178{
179 struct sigaction ae, ad;
180
181 ae.sa_handler = zthr_sig_exit;
182 ad.sa_handler = SIG_DFL;
183 memset( &(ae.sa_mask), 0, sizeof(sigset_t) );
184 ae.sa_flags = 0;
185 memset( &(ad.sa_mask), 0, sizeof(sigset_t) );
186 ad.sa_flags = 0;
187#ifdef OSF1
188 ae.sa_flags = SA_RESTART;
189 ad.sa_mask = 0;
190#endif
191 printf(" Activating signal %d handling for threads -> pthread_exit()\n",sig);
192 sigaction(sig, &ae, NULL);
193}
194
195
196/* ------ Classe ZMutex ------- */
197/*!
198 \class SOPHYA::ZMutex
199 \ingroup SysTools
200 \brief Wrapper for a pair of (Mutex,Cond.Var) objects.
201
202 This class implements an interface to the Mutual Exclusion objects
203 of the POSIX threads.
204 The ZMutex objects should be used to control acces from different threads
205 to common objects through the \b lock() and \b unlock() methods.
206 When the \b signal() method is called, one of the waiting threads
207 on the corresponding mutex object (\b ZMutex::wait()) is awakened.
208 All waiting threads on the mutex object are awakened when \b broadcast()
209 is called.
210 \sa SOPHYA::ZSync
211*/
212
213/*!
214 Constructor: Creates a associated pair of POSIX \c pthread_mutex_t
215 and \c pthread_cond_t objects
216 \param : if fgd == true , the destructor call pthread_mutex_destroy/pthread_cond_destroy
217*/
218ZMutex::ZMutex(bool fgd)
219{
220 _mutx = new pthread_mutex_t;
221 _condv = new pthread_cond_t;
222 int rc;
223 rc = pthread_mutex_init(_mutx, NULL);
224 CheckSt(rc,"ZMutex::ZMutex() Pb pthread_mutex_init");
225 rc = pthread_cond_init(_condv, NULL);
226 CheckSt(rc,"ZMutex::ZMutex() Pb pthread_cond_init");
227 _fgd = fgd;
228}
229
230ZMutex::~ZMutex()
231{
232 if (_fgd == false) return;
233 int rc;
234 rc = pthread_mutex_destroy(_mutx);
235 CheckSt(rc,"ZMutex::~ZMutex() Pb pthread_mutex_destroy");
236 rc = pthread_cond_destroy(_condv);
237 CheckSt(rc,"ZMutex::~ZMutex() Pb pthread_cond_destroy");
238 delete _mutx;
239 delete _condv;
240}
241
242/*!
243 \class SOPHYA::ZSync
244 \ingroup SysTools
245 \brief Wrapper/utility class ensuring synchronised execution of an instruction bloc.
246
247 This class can be used to insure that the execution of a given
248 part of the code is synchronised, i.e. only a single thread
249 goes through this at a given time.
250 The constructor acquires a lock on given \b ZMutex object,
251 which is released by the destructor.
252 The ZSync object should then be instanciated at the beginning of
253 the synchronised instruction bloc.
254 \sa SOPHYA::ZMutex
255*/
Note: See TracBrowser for help on using the repository browser.