]> git.mxchange.org Git - simgear.git/blob - simgear/threads/SGThread.hxx
Initial revision.
[simgear.git] / simgear / threads / SGThread.hxx
1 // SGThread - Simple pthread class wrappers.
2 //
3 // Written by Bernie Bright, started April 2001.
4 //
5 // Copyright (C) 2001  Bernard Bright - bbright@bigpond.net.au
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23 #ifndef SGTHREAD_HXX_INCLUDED
24 #define SGTHREAD_HXX_INCLUDED 1
25
26 #include <pthread.h>
27 #include <cassert>
28 #include <cerrno>
29
30 class SGThread;
31
32 extern "C" {
33     void* start_handler( void* );
34 };
35
36 /**
37  * Encapsulate generic threading methods.
38  * Users derive a class from SGThread and implement the run() member function.
39  */
40 class SGThread
41 {
42 public:
43
44     /**
45      * 
46      */
47     SGThread();
48
49     /**
50      * 
51      */
52     virtual ~SGThread();
53
54     /**
55      * 
56      */
57     int start();
58
59     /**
60      * 
61      */
62     void cancel();
63
64     /**
65      * 
66      */
67     void join();
68
69 protected:
70
71     /**
72      * 
73      */
74     virtual void run() = 0;
75
76 private:
77
78     /**
79      * 
80      */
81     pthread_t tid;
82
83     friend void* start_handler( void* );
84
85 private:
86     // Disable copying.
87     SGThread( const SGThread& );
88     SGThread& operator=( const SGThread& );
89 };
90
91 inline
92 SGThread::SGThread()
93 {
94 }
95
96 inline
97 SGThread::~SGThread()
98 {
99 }
100
101 inline int
102 SGThread::start()
103 {
104     int status = pthread_create( &tid, 0, start_handler, this );
105     assert( status == 0 );
106     return status;
107 }
108
109 inline void
110 SGThread::join()
111 {
112     int status = pthread_join( tid, 0 );
113     assert( status == 0 );
114 }
115
116 inline void
117 SGThread::cancel()
118 {
119     int status = pthread_cancel( tid );
120     assert( status == 0 );
121 }
122
123 /**
124  * A mutex is used to protect a section of code such that at any time
125  * only a single thread can execute the code.
126  */
127 class SGMutex
128 {
129     friend class SGCondition;
130
131 public:
132
133     /**
134      * Create a new mutex.
135      */
136     SGMutex();
137
138     /**
139      * Destroy a mutex object.
140      */
141     ~SGMutex();
142
143     /**
144      * 
145      */
146     void lock();
147
148     /**
149      * 
150      */
151     bool trylock();
152
153     /**
154      * 
155      */
156     void unlock();
157
158 protected:
159     pthread_mutex_t mutex;
160 };
161
162 inline SGMutex::SGMutex()
163 {
164     int status = pthread_mutex_init( &mutex, 0 );
165     assert( status == 0 );
166 }
167
168 inline SGMutex::~SGMutex()
169 {
170     int status = pthread_mutex_destroy( &mutex );
171     assert( status == 0 );
172 }
173
174 inline void SGMutex::lock()
175 {
176     int status = pthread_mutex_lock( &mutex );
177     assert( status == 0 );
178 }
179
180 inline void SGMutex::unlock()
181 {
182     int status = pthread_mutex_unlock( &mutex );
183     assert( status == 0 );
184 }
185
186 /**
187  * 
188  */
189 class SGCondition
190 {
191 public:
192     /**
193      * Create a new condition variable.
194      */
195     SGCondition();
196
197     /**
198      * Destroy the condition object.
199      */
200     ~SGCondition();
201
202     /**
203      * Wait for this condition variable to be signaled.
204      *
205      * @param SGMutex& reference to a locked mutex.
206      */
207     void wait( SGMutex& );
208
209     /**
210      * Wait for this condition variable to be signaled for at most
211      * 'ms' milliseconds.
212      *
213      * @param SGMutex& reference to a locked mutex.
214      * @param unsigned long milliseconds to wait for a signal.
215      *
216      * @return 
217      */
218     bool wait( SGMutex& mutex, unsigned long ms );
219
220     /**
221      * Wake one thread waiting on this condition variable.
222      */
223     void signal();
224
225     /**
226      * Wake all threads waiting on this condition variable.
227      */
228     void broadcast();
229
230 private:
231     // Disable copying.
232     SGCondition(const SGCondition& );
233     SGCondition& operator=(const SGCondition& );
234
235 private:
236
237     pthread_cond_t cond;
238 };
239
240 inline SGCondition::SGCondition()
241 {
242     int status = pthread_cond_init( &cond, 0 );
243     assert( status == 0 );
244 }
245
246 inline SGCondition::~SGCondition()
247 {
248     int status = pthread_cond_destroy( &cond );
249     assert( status == 0 );
250 }
251
252 inline void SGCondition::signal()
253 {
254     int status = pthread_cond_signal( &cond );
255     assert( status == 0 );
256 }
257
258 inline void SGCondition::broadcast()
259 {
260     int status = pthread_cond_broadcast( &cond );
261     assert( status == 0 );
262 }
263
264 inline void SGCondition::wait( SGMutex& mutex )
265 {
266     int status = pthread_cond_wait( &cond, &mutex.mutex );
267     assert( status == 0 );
268 }
269
270 #endif /* SGTHREAD_HXX_INCLUDED */