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 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
63 #if defined __GTHREAD_MUTEX_INIT
64 native_handle_type __tmp = __GTHREAD_MUTEX_INIT;
67 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
74 int __e = __gthread_mutex_lock(&_M_mutex);
76 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
78 __throw_system_error(__e);
84 // XXX EINVAL, EAGAIN, EBUSY
85 return !__gthread_mutex_trylock(&_M_mutex);
91 // XXX EINVAL, EAGAIN, EPERM
92 __gthread_mutex_unlock(&_M_mutex);
100 native_handle_type _M_mutex;
102 mutex& operator=(const mutex&);
107 class recursive_mutex
110 typedef __gthread_recursive_mutex_t native_handle_type;
114 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
115 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
116 native_handle_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
119 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
127 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
129 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
131 __throw_system_error(__e);
137 // XXX EINVAL, EAGAIN, EBUSY
138 return !__gthread_recursive_mutex_trylock(&_M_mutex);
144 // XXX EINVAL, EAGAIN, EBUSY
145 __gthread_recursive_mutex_unlock(&_M_mutex);
149 native_handle() { return _M_mutex; }
152 native_handle_type _M_mutex;
154 recursive_mutex(const recursive_mutex&);
155 recursive_mutex& operator=(const recursive_mutex&);
159 // class timed_mutex;
160 // class recursive_timed_mutex;
162 /// Do not acquire ownership of the mutex.
163 struct defer_lock_t { };
165 /// Try to acquire ownership of the mutex without blocking.
166 struct try_to_lock_t { };
168 /// Assume the calling thread has already obtained mutex ownership
170 struct adopt_lock_t { };
172 extern const defer_lock_t defer_lock;
173 extern const try_to_lock_t try_to_lock;
174 extern const adopt_lock_t adopt_lock;
176 /// Thrown to indicate errors with lock operations.
177 class lock_error : public exception
181 what() const throw();
184 /// @brief Scoped lock idiom.
185 // Acquire the mutex here with a constructor call, then release with
186 // the destructor call in accordance with RAII style.
187 template<typename _Mutex>
191 typedef _Mutex mutex_type;
193 explicit lock_guard(mutex_type& __m) : _M_device(__m)
194 { _M_device.lock(); }
196 lock_guard(mutex_type& __m, adopt_lock_t __a) : _M_device(__m)
197 { _M_device.lock(); }
200 { _M_device.unlock(); }
203 mutex_type& _M_device;
204 lock_guard(lock_guard const&);
205 lock_guard& operator=(lock_guard const&);
209 template<typename _Mutex>
213 typedef _Mutex mutex_type;
215 unique_lock() : _M_device(NULL), _M_owns(false) { }
217 explicit unique_lock(mutex_type& __m) : _M_device(&__m)
223 unique_lock(mutex_type& __m, defer_lock_t)
224 : _M_device(&__m), _M_owns(false) { }
226 unique_lock(mutex_type& __m, try_to_lock_t)
227 : _M_device(&__m), _M_owns(_M_device->try_lock()) { }
229 unique_lock(mutex_type& __m, adopt_lock_t)
230 : _M_device(&__m), _M_owns(true)
232 // XXX calling thread owns mutex
235 unique_lock(mutex_type& __m, const system_time& abs_time);
237 template<typename _Duration>
238 unique_lock(mutex_type& __m, const _Duration& rel_time);
246 unique_lock(unique_lock&&);
248 unique_lock& operator=(unique_lock&&);
254 if (_M_device && !_M_owns)
264 if (_M_device && !_M_owns)
265 __ret = _M_device->try_lock();
274 if (_M_device && _M_owns)
281 template<typename _Duration>
282 bool timed_lock(const _Duration& rel_time);
285 timed_lock(const system_time& abs_time);
288 swap(unique_lock&& __u);
293 mutex_type* __ret = _M_device;
300 owns_lock() const { return _M_owns; }
302 operator bool () const { return owns_lock(); }
306 { return _M_device; }
309 unique_lock(unique_lock const&);
310 unique_lock& operator=(unique_lock const&);
312 mutex_type* _M_device;
313 bool _M_owns; // XXX use atomic_bool
316 template<typename _Mutex>
318 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y);
320 template<typename _Mutex>
322 swap(unique_lock<_Mutex>&& __x, unique_lock<_Mutex>& __y);
324 template<typename _Mutex>
326 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y);
328 template<typename _L1, typename _L2, typename ..._L3>
330 try_lock(_L1&, _L2&, _L3&...);
332 template<typename _L1, typename _L2, typename ..._L3>
334 lock(_L1&, _L2&, _L3&...);
339 typedef __gthread_once_t __native_type;
343 __native_type __tmp = __GTHREAD_ONCE_INIT;
348 _M_get() { return _M_once; }
351 __native_type _M_once;
352 once_flag(const once_flag&);
353 once_flag& operator=(const once_flag&);
356 template<typename _Callable, typename... _Args>
358 call_once(once_flag& __once, _Callable __f, _Args&&... __args)
360 int __e = __gthread_once(&(__once._M_get()), __f(__args...));
362 __throw_system_error(__e);