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

Last change on this file since 3321 was 3219, checked in by ansari, 18 years ago

Ajout flag pour destroy_mutex selectif par le destructeur de ZMutex (pb erreur lors de sortie de piapp), Reza 12/04/2007

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