3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
4 // Free Software Foundation, Inc.
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)
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 // You should have received a copy of the GNU General Public License
18 // along with this library; see the file COPYING. If not, write to
19 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 // Boston, MA 02110-1301, USA.
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.
32 * This is a Standard C++ Library header.
35 #ifndef _GLIBCXX_MUTEX
36 #define _GLIBCXX_MUTEX 1
38 #pragma GCC system_header
40 #ifndef __GXX_EXPERIMENTAL_CXX0X__
41 # include <c++0x_warning.h>
46 #include <bits/functexcept.h>
47 #include <bits/gthr.h>
58 typedef __gthread_mutex_t native_handle_type;
62 #if defined __GTHREAD_MUTEX_INIT
63 native_handle_type __tmp = __GTHREAD_MUTEX_INIT;
66 int __e = __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
68 // EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
70 __throw_system_error(__e);
77 int __e = __gthread_mutex_lock(&_M_mutex);
79 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
81 __throw_system_error(__e);
87 int __e = __gthread_mutex_trylock(&_M_mutex);
89 // EINVAL, EAGAIN, EBUSY
91 __throw_system_error(__e);
99 int __e = __gthread_mutex_unlock(&_M_mutex);
101 // EINVAL, EAGAIN, EPERM
103 __throw_system_error(__e);
111 native_handle_type _M_mutex;
113 mutex& operator=(const mutex&);
118 class recursive_mutex
121 typedef __gthread_recursive_mutex_t native_handle_type;
125 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
126 native_handle_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
129 int __e = __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
131 // EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
133 __throw_system_error(__e);
141 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
143 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
145 __throw_system_error(__e);
151 int __e = __gthread_recursive_mutex_trylock(&_M_mutex);
153 // EINVAL, EAGAIN, EBUSY
155 __throw_system_error(__e);
163 int __e = __gthread_recursive_mutex_unlock(&_M_mutex);
165 // EINVAL, EAGAIN, EBUSY
167 __throw_system_error(__e);
171 native_handle() { return _M_mutex; }
174 native_handle_type _M_mutex;
176 recursive_mutex(const recursive_mutex&);
177 recursive_mutex& operator=(const recursive_mutex&);
181 // class timed_mutex;
182 // class recursive_timed_mutex;
184 /// Do not acquire ownership of the mutex.
185 struct defer_lock_t { };
187 /// Try to acquire ownership of the mutex without blocking.
188 struct try_to_lock_t { };
190 /// Assume the calling thread has already obtained mutex ownership
192 struct adopt_lock_t { };
194 extern const defer_lock_t defer_lock;
195 extern const try_to_lock_t try_to_lock;
196 extern const adopt_lock_t adopt_lock;
198 /// Thrown to indicate errors with lock operations.
199 class lock_error : public exception
203 what() const throw();
206 /// @brief Scoped lock idiom.
207 // Acquire the mutex here with a constructor call, then release with
208 // the destructor call in accordance with RAII style.
209 template<typename _Mutex>
213 typedef _Mutex mutex_type;
215 explicit lock_guard(mutex_type& __m) : _M_device(__m)
216 { _M_device.lock(); }
218 lock_guard(mutex_type& __m, adopt_lock_t __a) : _M_device(__m)
219 { _M_device.lock(); }
222 { _M_device.unlock(); }
225 mutex_type& _M_device;
226 lock_guard(lock_guard const&);
227 lock_guard& operator=(lock_guard const&);
231 template<typename _Mutex>
235 typedef _Mutex mutex_type;
237 unique_lock() : _M_device(NULL), _M_owns(false) { }
239 explicit unique_lock(mutex_type& __m) : _M_device(&__m)
245 unique_lock(mutex_type& __m, defer_lock_t)
246 : _M_device(&__m), _M_owns(false) { }
248 unique_lock(mutex_type& __m, try_to_lock_t)
249 : _M_device(&__m), _M_owns(_M_device->try_lock()) { }
251 unique_lock(mutex_type& __m, adopt_lock_t)
252 : _M_device(&__m), _M_owns(true)
254 // XXX calling thread owns mutex
257 unique_lock(mutex_type& __m, const system_time& abs_time);
259 template<typename _Duration>
260 unique_lock(mutex_type& __m, const _Duration& rel_time);
268 unique_lock(unique_lock&&);
270 unique_lock& operator=(unique_lock&&);
276 if (_M_device && !_M_owns)
286 if (_M_device && !_M_owns)
287 __ret = _M_device->try_lock();
296 if (_M_device && _M_owns)
303 template<typename _Duration>
304 bool timed_lock(const _Duration& rel_time);
307 timed_lock(const system_time& abs_time);
310 swap(unique_lock&& __u);
315 mutex_type* __ret = _M_device;
322 owns_lock() const { return _M_owns; }
324 operator bool () const { return owns_lock(); }
328 { return _M_device; }
331 unique_lock(unique_lock const&);
332 unique_lock& operator=(unique_lock const&);
334 mutex_type* _M_device;
335 bool _M_owns; // XXX use atomic_bool
338 template<typename _Mutex>
340 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y);
342 template<typename _Mutex>
344 swap(unique_lock<_Mutex>&& __x, unique_lock<_Mutex>& __y);
346 template<typename _Mutex>
348 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y);
350 template<typename _L1, typename _L2, typename ..._L3>
352 try_lock(_L1&, _L2&, _L3&...);
354 template<typename _L1, typename _L2, typename ..._L3>
356 lock(_L1&, _L2&, _L3&...);
361 typedef __gthread_once_t __native_type;
363 once_flag() : _M_once(__GTHREAD_ONCE_INIT) { }
366 _M_get() { return _M_once; }
369 __native_type _M_once;
370 once_flag(const once_flag&);
371 once_flag& operator=(const once_flag&);
374 template<typename _Callable, typename... _Args>
376 call_once(once_flag& __once, _Callable __f, _Args&&... __args)
378 int __e = __gthread_once(&(__once._M_get()), __f(__args...));
380 __throw_system_error(__e);