]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libstdc++-v3/contrib/libstdc++-v3-4.3.3/include/ext/concurrence.h
Inital import
[l4.git] / l4 / pkg / libstdc++-v3 / contrib / libstdc++-v3-4.3.3 / include / ext / concurrence.h
1 // Support for concurrent programing -*- C++ -*-
2
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 // USA.
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 /** @file concurrence.h
32  *  This is an internal header file, included by other library headers.
33  *  You should not attempt to use it directly.
34  */
35
36 #ifndef _CONCURRENCE_H
37 #define _CONCURRENCE_H 1
38
39 #include <exception>
40 #include <bits/gthr.h> 
41 #include <bits/functexcept.h>
42
43 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
44
45   // Available locking policies:
46   // _S_single    single-threaded code that doesn't need to be locked.
47   // _S_mutex     multi-threaded code that requires additional support
48   //              from gthr.h or abstraction layers in concurrence.h.
49   // _S_atomic    multi-threaded code using atomic operations.
50   enum _Lock_policy { _S_single, _S_mutex, _S_atomic }; 
51
52   // Compile time constant that indicates prefered locking policy in
53   // the current configuration.
54   static const _Lock_policy __default_lock_policy = 
55 #ifdef __GTHREADS
56 #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
57      && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))
58   _S_atomic;
59 #else
60   _S_mutex;
61 #endif
62 #else
63   _S_single;
64 #endif
65
66   // NB: As this is used in libsupc++, need to only depend on
67   // exception. No stdexception classes, no use of std::string.
68   class __concurrence_lock_error : public std::exception
69   {
70   public:
71     virtual char const*
72     what() const throw()
73     { return "__gnu_cxx::__concurrence_lock_error"; }
74   };
75
76   class __concurrence_unlock_error : public std::exception
77   {
78   public:
79     virtual char const*
80     what() const throw()
81     { return "__gnu_cxx::__concurrence_unlock_error"; }
82   };
83
84   class __concurrence_broadcast_error : public std::exception
85   {
86   public:
87     virtual char const*
88     what() const throw()
89     { return "__gnu_cxx::__concurrence_broadcast_error"; }
90   };
91
92   class __concurrence_wait_error : public std::exception
93   {
94   public:
95     virtual char const*
96     what() const throw()
97     { return "__gnu_cxx::__concurrence_wait_error"; }
98   };
99
100   // Substitute for concurrence_error object in the case of -fno-exceptions.
101   inline void
102   __throw_concurrence_lock_error()
103   {
104 #if __EXCEPTIONS
105     throw __concurrence_lock_error();
106 #else
107     __builtin_abort();
108 #endif
109   }
110
111   inline void
112   __throw_concurrence_unlock_error()
113   {
114 #if __EXCEPTIONS
115     throw __concurrence_unlock_error();
116 #else
117     __builtin_abort();
118 #endif
119   }
120
121 #ifdef __GTHREAD_HAS_COND
122   inline void
123   __throw_concurrence_broadcast_error()
124   {
125 #if __EXCEPTIONS
126     throw __concurrence_broadcast_error();
127 #else
128     __builtin_abort();
129 #endif
130   }
131
132   inline void
133   __throw_concurrence_wait_error()
134   {
135 #if __EXCEPTIONS
136     throw __concurrence_wait_error();
137 #else
138     __builtin_abort();
139 #endif
140   }
141 #endif
142  
143   class __mutex 
144   {
145   private:
146     __gthread_mutex_t _M_mutex;
147
148     __mutex(const __mutex&);
149     __mutex& operator=(const __mutex&);
150
151   public:
152     __mutex() 
153     { 
154 #if __GTHREADS
155       if (__gthread_active_p())
156         {
157 #if defined __GTHREAD_MUTEX_INIT
158           __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
159           _M_mutex = __tmp;
160 #else
161           __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); 
162 #endif
163         }
164 #endif 
165     }
166
167     void lock()
168     {
169 #if __GTHREADS
170       if (__gthread_active_p())
171         {
172           if (__gthread_mutex_lock(&_M_mutex) != 0)
173             __throw_concurrence_lock_error();
174         }
175 #endif
176     }
177     
178     void unlock()
179     {
180 #if __GTHREADS
181       if (__gthread_active_p())
182         {
183           if (__gthread_mutex_unlock(&_M_mutex) != 0)
184             __throw_concurrence_unlock_error();
185         }
186 #endif
187     }
188
189     __gthread_mutex_t* gthread_mutex(void)
190       { return &_M_mutex; }
191   };
192
193   class __recursive_mutex 
194   {
195   private:
196     __gthread_recursive_mutex_t _M_mutex;
197
198     __recursive_mutex(const __recursive_mutex&);
199     __recursive_mutex& operator=(const __recursive_mutex&);
200
201   public:
202     __recursive_mutex() 
203     { 
204 #if __GTHREADS
205       if (__gthread_active_p())
206         {
207 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
208           __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
209           _M_mutex = __tmp;
210 #else
211           __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 
212 #endif
213         }
214 #endif 
215     }
216
217     void lock()
218     { 
219 #if __GTHREADS
220       if (__gthread_active_p())
221         {
222           if (__gthread_recursive_mutex_lock(&_M_mutex) != 0)
223             __throw_concurrence_lock_error();
224         }
225 #endif
226     }
227     
228     void unlock()
229     { 
230 #if __GTHREADS
231       if (__gthread_active_p())
232         {
233           if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0)
234             __throw_concurrence_unlock_error();
235         }
236 #endif
237     }
238
239     __gthread_recursive_mutex_t* gthread_recursive_mutex(void)
240       { return &_M_mutex; }
241   };
242
243   /// Scoped lock idiom.
244   // Acquire the mutex here with a constructor call, then release with
245   // the destructor call in accordance with RAII style.
246   class __scoped_lock
247   {
248   public:
249     typedef __mutex __mutex_type;
250
251   private:
252     __mutex_type& _M_device;
253
254     __scoped_lock(const __scoped_lock&);
255     __scoped_lock& operator=(const __scoped_lock&);
256
257   public:
258     explicit __scoped_lock(__mutex_type& __name) : _M_device(__name)
259     { _M_device.lock(); }
260
261     ~__scoped_lock() throw()
262     { _M_device.unlock(); }
263   };
264
265 #ifdef __GTHREAD_HAS_COND
266   class __cond
267   {
268   private:
269     __gthread_cond_t _M_cond;
270
271     __cond(const __cond&);
272     __cond& operator=(const __cond&);
273
274   public:
275     __cond() 
276     { 
277 #if __GTHREADS
278       if (__gthread_active_p())
279         {
280 #if defined __GTHREAD_COND_INIT
281           __gthread_cond_t __tmp = __GTHREAD_COND_INIT;
282           _M_cond = __tmp;
283 #else
284           __GTHREAD_COND_INIT_FUNCTION(&_M_cond);
285 #endif
286         }
287 #endif 
288     }
289
290     void broadcast()
291     {
292 #if __GTHREADS
293       if (__gthread_active_p())
294         {
295           if (__gthread_cond_broadcast(&_M_cond) != 0)
296             __throw_concurrence_broadcast_error();
297         }
298 #endif
299     }
300
301     void wait(__mutex *mutex)
302     {
303 #if __GTHREADS
304       {
305           if (__gthread_cond_wait(&_M_cond, mutex->gthread_mutex()) != 0)
306             __throw_concurrence_wait_error();
307       }
308 #endif
309     }
310
311     void wait_recursive(__recursive_mutex *mutex)
312     {
313 #if __GTHREADS
314       {
315           if (__gthread_cond_wait_recursive(&_M_cond,
316                                             mutex->gthread_recursive_mutex())
317               != 0)
318             __throw_concurrence_wait_error();
319       }
320 #endif
321     }
322   };
323 #endif
324
325 _GLIBCXX_END_NAMESPACE
326
327 #endif