Merge from mainline (163495:164578).
[official-gcc/graphite-test-results.git] / libstdc++-v3 / include / ext / concurrence.h
blob6f8e10bfeef0f8b5cf5b275d40d08355adea2362
1 // Support for concurrent programing -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 3, or (at your option)
10 // any later version.
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.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
26 /** @file concurrence.h
27 * This is an internal header file, included by other library headers.
28 * You should not attempt to use it directly.
31 #ifndef _CONCURRENCE_H
32 #define _CONCURRENCE_H 1
34 #pragma GCC system_header
36 #include <exception>
37 #include <bits/gthr.h>
38 #include <bits/functexcept.h>
40 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
42 // Available locking policies:
43 // _S_single single-threaded code that doesn't need to be locked.
44 // _S_mutex multi-threaded code that requires additional support
45 // from gthr.h or abstraction layers in concurrence.h.
46 // _S_atomic multi-threaded code using atomic operations.
47 enum _Lock_policy { _S_single, _S_mutex, _S_atomic };
49 // Compile time constant that indicates prefered locking policy in
50 // the current configuration.
51 static const _Lock_policy __default_lock_policy =
52 #ifdef __GTHREADS
53 #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
54 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))
55 _S_atomic;
56 #else
57 _S_mutex;
58 #endif
59 #else
60 _S_single;
61 #endif
63 // NB: As this is used in libsupc++, need to only depend on
64 // exception. No stdexception classes, no use of std::string.
65 class __concurrence_lock_error : public std::exception
67 public:
68 virtual char const*
69 what() const throw()
70 { return "__gnu_cxx::__concurrence_lock_error"; }
73 class __concurrence_unlock_error : public std::exception
75 public:
76 virtual char const*
77 what() const throw()
78 { return "__gnu_cxx::__concurrence_unlock_error"; }
81 class __concurrence_broadcast_error : public std::exception
83 public:
84 virtual char const*
85 what() const throw()
86 { return "__gnu_cxx::__concurrence_broadcast_error"; }
89 class __concurrence_wait_error : public std::exception
91 public:
92 virtual char const*
93 what() const throw()
94 { return "__gnu_cxx::__concurrence_wait_error"; }
97 // Substitute for concurrence_error object in the case of -fno-exceptions.
98 inline void
99 __throw_concurrence_lock_error()
101 #if __EXCEPTIONS
102 throw __concurrence_lock_error();
103 #else
104 __builtin_abort();
105 #endif
108 inline void
109 __throw_concurrence_unlock_error()
111 #if __EXCEPTIONS
112 throw __concurrence_unlock_error();
113 #else
114 __builtin_abort();
115 #endif
118 #ifdef __GTHREAD_HAS_COND
119 inline void
120 __throw_concurrence_broadcast_error()
122 #if __EXCEPTIONS
123 throw __concurrence_broadcast_error();
124 #else
125 __builtin_abort();
126 #endif
129 inline void
130 __throw_concurrence_wait_error()
132 #if __EXCEPTIONS
133 throw __concurrence_wait_error();
134 #else
135 __builtin_abort();
136 #endif
138 #endif
140 class __mutex
142 private:
143 __gthread_mutex_t _M_mutex;
145 __mutex(const __mutex&);
146 __mutex& operator=(const __mutex&);
148 public:
149 __mutex()
151 #if __GTHREADS
152 if (__gthread_active_p())
154 #if defined __GTHREAD_MUTEX_INIT
155 __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
156 _M_mutex = __tmp;
157 #else
158 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
159 #endif
161 #endif
164 void lock()
166 #if __GTHREADS
167 if (__gthread_active_p())
169 if (__gthread_mutex_lock(&_M_mutex) != 0)
170 __throw_concurrence_lock_error();
172 #endif
175 void unlock()
177 #if __GTHREADS
178 if (__gthread_active_p())
180 if (__gthread_mutex_unlock(&_M_mutex) != 0)
181 __throw_concurrence_unlock_error();
183 #endif
186 __gthread_mutex_t* gthread_mutex(void)
187 { return &_M_mutex; }
190 class __recursive_mutex
192 private:
193 __gthread_recursive_mutex_t _M_mutex;
195 __recursive_mutex(const __recursive_mutex&);
196 __recursive_mutex& operator=(const __recursive_mutex&);
198 public:
199 __recursive_mutex()
201 #if __GTHREADS
202 if (__gthread_active_p())
204 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
205 __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
206 _M_mutex = __tmp;
207 #else
208 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
209 #endif
211 #endif
214 void lock()
216 #if __GTHREADS
217 if (__gthread_active_p())
219 if (__gthread_recursive_mutex_lock(&_M_mutex) != 0)
220 __throw_concurrence_lock_error();
222 #endif
225 void unlock()
227 #if __GTHREADS
228 if (__gthread_active_p())
230 if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0)
231 __throw_concurrence_unlock_error();
233 #endif
236 __gthread_recursive_mutex_t* gthread_recursive_mutex(void)
237 { return &_M_mutex; }
240 /// Scoped lock idiom.
241 // Acquire the mutex here with a constructor call, then release with
242 // the destructor call in accordance with RAII style.
243 class __scoped_lock
245 public:
246 typedef __mutex __mutex_type;
248 private:
249 __mutex_type& _M_device;
251 __scoped_lock(const __scoped_lock&);
252 __scoped_lock& operator=(const __scoped_lock&);
254 public:
255 explicit __scoped_lock(__mutex_type& __name) : _M_device(__name)
256 { _M_device.lock(); }
258 ~__scoped_lock() throw()
259 { _M_device.unlock(); }
262 #ifdef __GTHREAD_HAS_COND
263 class __cond
265 private:
266 __gthread_cond_t _M_cond;
268 __cond(const __cond&);
269 __cond& operator=(const __cond&);
271 public:
272 __cond()
274 #if __GTHREADS
275 if (__gthread_active_p())
277 #if defined __GTHREAD_COND_INIT
278 __gthread_cond_t __tmp = __GTHREAD_COND_INIT;
279 _M_cond = __tmp;
280 #else
281 __GTHREAD_COND_INIT_FUNCTION(&_M_cond);
282 #endif
284 #endif
287 void broadcast()
289 #if __GTHREADS
290 if (__gthread_active_p())
292 if (__gthread_cond_broadcast(&_M_cond) != 0)
293 __throw_concurrence_broadcast_error();
295 #endif
298 void wait(__mutex *mutex)
300 #if __GTHREADS
302 if (__gthread_cond_wait(&_M_cond, mutex->gthread_mutex()) != 0)
303 __throw_concurrence_wait_error();
305 #endif
308 void wait_recursive(__recursive_mutex *mutex)
310 #if __GTHREADS
312 if (__gthread_cond_wait_recursive(&_M_cond,
313 mutex->gthread_recursive_mutex())
314 != 0)
315 __throw_concurrence_wait_error();
317 #endif
320 #endif
322 _GLIBCXX_END_NAMESPACE
324 #endif