Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
_mutex.h
Go to the documentation of this file.
1
32#ifndef _RWSTD_RW_MUTEX_H_INCLUDED
33#define _RWSTD_RW_MUTEX_H_INCLUDED
34
35
36#if __GNUG__ >= 3
37# pragma GCC system_header
38#endif // gcc >= 3
39
40
41#ifndef _RWSTD_RW_DEFS_H_INCLUDED
42# include <rw/_defs.h>
43#endif // _RWSTD_RW_DEFS_H_INCLUDED
44
45
46#ifndef _RWSTD_RW_ATOMIC_H_INCLUDED
47# include <rw/_atomic.h>
48#endif // _RWSTD_RW_ATOMIC_H_INCLUDED
49
50
51#ifdef _RWSTD_REENTRANT
52
53# ifndef _RWSTD_RW_EXCEPTION_H_INCLUDED
54# include <rw/_exception.h>
55# endif // _RWSTD_RW_EXCEPTION_INCLUDED
56
57# ifndef _RWSTD_RW_ERROR_H_INCLUDED
58# include <rw/_error.h>
59# endif // _RWSTD_RW_ERROR_H_INCLUDED
60
61
62// work around SunOS 5.{8,9}/SunPro bug (see PR #26255)
63# if defined (__SunOS_5_8) || defined (__SunOS_5_9)
64# undef _TIME_T
65# endif // __SunOS_5_{8,9}
66
67# if defined (_RWSTD_SOLARIS_THREADS) // assuming Solaris 2.1 or greater
68# include <rw/_mutex-solaris.h>
69# elif defined (_RWSTD_POSIX_THREADS)
70# include <rw/_mutex-pthread.h>
71# elif defined (_RWSTD_DCE_THREADS)
72# include <rw/_mutex-dce.h>
73# elif defined (_WIN32)
74# include <rw/_mutex-win32.h>
75# elif defined (__OS2__)
76# include <rw/_mutex-os2.h>
77# else
78# error unknown thread environment
79# endif
80
81
82# if defined(_RWSTD_NO_STATIC_MUTEX_INIT)
83# include <new>
84# endif //_RWSTD_NO_STATIC_MUTEX_INIT
85
86
88
89// a using declaration (rather than a directive)
90// used to work around yet another MSVC 6.0 bug
92
93class __rw_thread_error : public exception
94{
95public:
96 __rw_thread_error () _THROWS (())
97 : exception () { }
98
99 virtual const char* what () const _THROWS (()) {
100 return "thread synchronization error";
101 }
102};
103
104
105// POD type with no user-defined ctor or dtor facilitates static
106// initialization of mutex objects with static storage duration
107// (important during library initialziation time)
108class _RWSTD_EXPORT __rw_mutex_base
109{
110public:
111
112 void _C_acquire () {
113# if !defined (__HP_aCC) || __HP_aCC > 32700
114 if (0 != _RWSTD_MUTEX_LOCK (_C_mutex))
115 _RW::__rw_throw (_RWSTD_ERROR_RUNTIME_ERROR,
116 "synchronization error");
117# else
118 // working around an HP aCC 3.27 bug JAGac88738
119 _RWSTD_MUTEX_LOCK (_C_mutex);
120# endif // !defined (__HP_aCC) || __HP_aCC > 32700
121 }
122
123 void _C_release ();
124
125# ifdef _RWSTD_NO_STATIC_MUTEX_INIT
126
127 // static initialization not an option, define ctor and dtor
128 // and make member mutex private
129
130 __rw_mutex_base ();
131
132 ~__rw_mutex_base ();
133
134private:
135
136 // not defined
137 __rw_mutex_base (const __rw_mutex_base&);
138 __rw_mutex_base& operator= (const __rw_mutex_base&);
139
140# endif // _RWSTD_NO_STATIC_MUTEX_INIT
141
142 _RWSTD_MUTEX_T _C_mutex; // the real thing
143};
144
145
146inline void __rw_mutex_base::_C_release ()
147{
148 // we should NOT throw from here as _C_release will typically be called
149 // during the destruction of local objects such as __rw_guard (perhaps
150 // due to another exception)
151 _RWSTD_MUTEX_UNLOCK (_C_mutex);
152}
153
154
155// non-POD type, always initializes mutex data member via a function call
156class _RWSTD_EXPORT __rw_mutex: public __rw_mutex_base
157{
158public:
159
160# ifndef _RWSTD_NO_STATIC_MUTEX_INIT
161
162 __rw_mutex ();
163
164 ~__rw_mutex ();
165
166private:
167
168 // not defined
169 __rw_mutex (const __rw_mutex&);
170 __rw_mutex& operator= (const __rw_mutex&);
171
172# endif // _RWSTD_NO_STATIC_MUTEX_INIT
173
174};
175
176
177# ifndef _RWSTD_NO_STATIC_MUTEX_INIT
178
179// helper factory class - static member is guranteed to be constructed
180// during static initialization; objects of this POD class are not
181// destroyed during program termination (important to allow them
182// to be used in dtors of other objects with static storage duration)
183template <class _TypeT>
184struct __rw_static_mutex
185{
186 static __rw_mutex_base _C_mutex;
187};
188
189
190template <class _TypeT>
191__rw_mutex_base __rw_static_mutex<_TypeT>::_C_mutex
192
193# ifdef _RWSTD_MUTEX_INITIALIZER
194
196
197# undef _RWSTD_MUTEX_INITIALIZER
198# endif // _RWSTD_MUTEX_INITIALIZER
199 ;
200
201# if _RWSTD_INSTANTIATE (_STATIC_MUTEX, _INT)
202
203// explicitly instantiated to work around a g++ 2.95.2 bug on COFF systems
204// (such as IBM AIX or DEC OSF1) where it "forgets" to do so implicitly for
205// explicitly initialized static data members
206_RWSTD_INSTANTIATE_1 (class _RWSTD_TI_EXPORT __rw_static_mutex<int>);
207_RWSTD_INSTANTIATE_1 (class _RWSTD_TI_EXPORT __rw_static_mutex<size_t>);
208
209# endif // _RWSTD_INSTANTIATE (_STATIC_MUTEX, _INT)
210
211
212inline __rw_mutex::__rw_mutex ()
213
214# else // if defined (_RWSTD_NO_STATIC_MUTEX_INIT)
215
216inline __rw_mutex_base::__rw_mutex_base ()
217
218# endif // _RWSTD_NO_STATIC_MUTEX_INIT
219{
220 if (0 != _RWSTD_MUTEX_INIT (_C_mutex))
221 _RW::__rw_throw (_RWSTD_ERROR_RUNTIME_ERROR, "synchronization error");
222}
223
224# ifndef _RWSTD_NO_STATIC_MUTEX_INIT
225
226inline __rw_mutex::~__rw_mutex ()
227
228# else // if defined (_RWSTD_NO_STATIC_MUTEX_INIT)
229
230inline __rw_mutex_base::~__rw_mutex_base ()
231
232# endif // _RWSTD_NO_STATIC_MUTEX_INIT
233{
234 _RWSTD_MUTEX_DESTROY (_C_mutex);
235}
236
237// type used in instantiating __rw_get_static_mutex
238template<class _TypeT, int _IntI> struct __rw_type { };
239
240// mutex factory function avoids problematic initialization dependencies
241// introduced by definitions of mutexes with static storage duration
242// instead of defining a static mutex member that may not be initialized
243// before first use, a non-local class may either declare a unique type
244// (enum or class) or use itself as this type, and call this template
245// function with a ptr to that type to obtain an initialized mutex object
246// that is the same for each unique type passed to the function
247
248# ifndef _RWSTD_NO_STATIC_MUTEX_INIT
249
250template <class _TypeT>
251inline
252__rw_mutex_base& __rw_get_static_mutex (_TypeT*)
253{
254 // POD mutex already initialized during static initialization
255 return __rw_static_mutex<_TypeT>::_C_mutex;
256}
257
258# else // if defined (_RWSTD_NO_STATIC_MUTEX_INIT)
259
260# ifdef _INLINE_WITH_STATICS
261
262template <class _TypeT>
264__rw_mutex_base& __rw_get_static_mutex (_TypeT*)
265
266# else // if !defined (_INLINE_WITH_STATICS)
267
268template <class _TypeT>
269__rw_mutex_base& __rw_get_static_mutex (_TypeT*)
270
271# endif // _INLINE_WITH_STATICS
272
273{
274 // allocate properly aligned memory for static mutex (necessary
275 // to prevent static local mutex from being destroyed during
276 // program termination)
277 union __mutex_buf_t {
278 long double __pad; // force alignment (must be first)
279 char __buf [sizeof (__rw_mutex_base)];
280 };
281
282 // using a named union to work around a bug in HP aCC 3.14.10 (JAGad03246)
283 static __mutex_buf_t __mutex_buf;
284
285 // initialize mutex reference to refer to the static buffer space
286 __rw_mutex_base &__mutex =
287 _RWSTD_REINTERPRET_CAST (__rw_mutex_base&, __mutex_buf);
288
289 // keep track of number of mutex initialization attempts
290 // although `init' may reach a value greater than 1, `mutex'
291 // will (should) never be multiply initialized
292
293 // implicit initialization used to prevent a g++ 2.95.2 warning on Tru64
294 // sorry: semantics of inline function static data are wrong (you'll wind
295 // up with multiple copies)
296 static volatile int __cntr /* = 0 */; // initialization counter
297
298# if !defined (_RWSTD_NO_ATOMIC_OPS) && !defined (_RWSTD_NO_INT_ATOMIC_OPS)
299 // MT safe
300 // cast __cntr to int& (see STDCXX-792)
301 // casting should be removed after fixing STDCXX-794
302 if (0 == __cntr && 1 == _RWSTD_ATOMIC_PREINCREMENT (
303 _RWSTD_CONST_CAST (int&, __cntr), false))
304# else // _RWSTD_NO_ATOMIC_OPS || _RWSTD_NO_INT_ATOMIC_OPS
305 // not so safe (volatile should help)
306 if (0 == __cntr && 1 == ++__cntr)
307# endif // !_RWSTD_NO_ATOMIC_OPS && !_RWSTD_NO_INT_ATOMIC_OPS
308
309 {
310 // manually initialize `mutex' via a call to placement new
311 new (&__mutex) __rw_mutex_base ();
312
313 // indicate that `mutex' has been fully initialized
314 // (unlikely that we'll have more than 1000 threads)
315 __cntr += 1000;
316 }
317 else
318 // busywait until `mutex' has been completely initialized
319 while (__cntr < 1000);
320
321 return __mutex;
322}
323
324# endif //_RWSTD_NO_STATIC_MUTEX_INIT
325
326
327// clean up
328# undef _RWSTD_MUTEX_LOCK
329# undef _RWSTD_MUTEX_UNLOCK
330# undef _RWSTD_MUTEX_T
331
332
333// allows safe use of a mutex in the presence of exceptions
334class __rw_guard
335{
336 __rw_mutex_base *_C_mutex;
337
338 // undefined
339 __rw_guard& operator= (const __rw_guard&);
340
341public:
342
343 __rw_guard (__rw_guard &__rhs)
344 : _C_mutex (__rhs._C_mutex) {
345 __rhs._C_mutex = 0;
346 }
347
348 __rw_guard (__rw_mutex_base &__mutex): _C_mutex (&__mutex) {
349 _C_mutex->_C_acquire ();
350 }
351
352 __rw_guard (__rw_mutex_base *__mutex): _C_mutex (__mutex) {
353 if (_C_mutex)
354 _C_mutex->_C_acquire ();
355 }
356
357 ~__rw_guard () {
358 if (_C_mutex)
359 _C_mutex->_C_release ();
360 }
361
362 __rw_mutex_base* _C_set (__rw_mutex_base *__mutex) {
363 __rw_mutex_base *__tmp = _C_mutex;
364 return _C_mutex = __mutex, __tmp;
365 }
366};
367
368
369// base class for obects required to guarantee some degree of MT safety
370struct _RWSTD_EXPORT __rw_synchronized
371{
372 __rw_mutex _C_mutex;
373
374 void _C_lock () {
375 _C_mutex._C_acquire ();
376 }
377
378 void _C_unlock () {
379 _C_mutex._C_release ();
380 }
381
382 __rw_guard _C_guard () {
383 __rw_guard __guard (_C_mutex);
384 return __guard;
385 }
386};
387
388} // namespace __rw
389
390
391// include atomic functions using mutex object
392# ifndef _RWSTD_RW_ATOMIC_MUTEX_H_INCLUDED
393# include <rw/_atomic-mutex.h>
394# endif // _RWSTD_RW_ATOMIC_MUTEX_H_INCLUDED
395
396
397#else // if !defined (_RWSTD_REENTRANT)
398
400
401// dummy classes used as a base class in single-threaded environments
402
403struct __rw_mutex_base
404{
405 void _C_acquire () { }
406
407 void _C_release () { }
408};
409
410
411struct _RWSTD_EXPORT __rw_mutex: public __rw_mutex_base
412{
413};
414
415
416struct __rw_guard
417{
418 __rw_guard (__rw_mutex_base&) { }
419
420 __rw_guard (__rw_mutex_base*) { }
421
422 __rw_mutex_base* _C_set (__rw_mutex_base*) {
423 return 0;
424 }
425};
426
427
428struct __rw_synchronized
429{
430 // static so that it takes up no space
431 static _RWSTD_EXPORT __rw_mutex _C_mutex;
432
433 void _C_lock () { }
434
435 void _C_unlock () { }
436
437 __rw_guard _C_guard () {
438 return __rw_guard (_C_mutex);
439 }
440};
441
442
443} // namespace __rw
444
445
446#endif // _RWSTD_REENTRANT
447
448// clean up
449#ifdef _RWSTD_NO_CHAR_ATOMIC_OPS
450# undef _RWSTD_NO_CHAR_ATOMIC_OPS
451#endif
452
453#ifdef _RWSTD_NO_SHORT_ATOMIC_OPS
454# undef _RWSTD_NO_SHORT_ATOMIC_OPS
455#endif
456
457#ifdef _RWSTD_NO_INT_ATOMIC_OPS
458# undef _RWSTD_NO_INT_ATOMIC_OPS
459#endif
460
461#ifdef _RWSTD_NO_LONG_ATOMIC_OPS
462# undef _RWSTD_NO_LONG_ATOMIC_OPS
463#endif
464
465#ifdef _RWSTD_NO_LLONG_ATOMIC_OPS
466# undef _RWSTD_NO_LLONG_ATOMIC_OPS
467#endif
468
469#endif // _RWSTD_RW_MUTEX_H_INCLUDED
#define _THROWS()
#define _INLINE_WITH_STATICS
Definition _config.h:338
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_INSTANTIATE_1(arg)
Definition _defs.h:1374
#define _RWSTD_ATOMIC_PREINCREMENT(x, ignore)
Definition _defs.h:699
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_TI_EXPORT
Definition _defs.h:1331
#define _USING(name)
Definition _defs.h:568
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
#define _RWSTD_ERROR_RUNTIME_ERROR
Definition _error.h:94
#define _RWSTD_MUTEX_DESTROY(mutex)
Definition _mutex-dce.h:40
#define _RWSTD_MUTEX_T
Definition _mutex-dce.h:43
#define _RWSTD_MUTEX_UNLOCK(mutex)
Definition _mutex-dce.h:42
#define _RWSTD_MUTEX_INIT(mutex)
Definition _mutex-dce.h:38
#define _RWSTD_MUTEX_LOCK(mutex)
Definition _mutex-dce.h:41
#define _RWSTD_MUTEX_INITIALIZER