1 | // std::mutex implementation -*- C++ -*-  |
2 |   |
3 | // Copyright (C) 2003-2019 Free Software Foundation, Inc.  |
4 | //  |
5 | // This file is part of the GNU ISO C++ Library. This library is free  |
6 | // software; you can redistribute it and/or modify it under the  |
7 | // terms of the GNU General Public License as published by the  |
8 | // Free Software Foundation; either version 3, or (at your option)  |
9 | // any later version.  |
10 |   |
11 | // This library is distributed in the hope that it will be useful,  |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of  |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  |
14 | // GNU General Public License for more details.  |
15 |   |
16 | // Under Section 7 of GPL version 3, you are granted additional  |
17 | // permissions described in the GCC Runtime Library Exception, version  |
18 | // 3.1, as published by the Free Software Foundation.  |
19 |   |
20 | // You should have received a copy of the GNU General Public License and  |
21 | // a copy of the GCC Runtime Library Exception along with this program;  |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see  |
23 | // <http://www.gnu.org/licenses/>.  |
24 |   |
25 | /** @file bits/std_mutex.h  |
26 | * This is an internal header file, included by other library headers.  |
27 | * Do not attempt to use it directly. @headername{mutex}  |
28 | */  |
29 |   |
30 | #ifndef _GLIBCXX_MUTEX_H  |
31 | #define _GLIBCXX_MUTEX_H 1  |
32 |   |
33 | #pragma GCC system_header  |
34 |   |
35 | #if __cplusplus < 201103L  |
36 | # include <bits/c++0x_warning.h>  |
37 | #else  |
38 |   |
39 | #include <system_error>  |
40 | #include <bits/functexcept.h>  |
41 | #include <bits/gthr.h>  |
42 |   |
43 | namespace std _GLIBCXX_VISIBILITY(default)  |
44 | {  |
45 | _GLIBCXX_BEGIN_NAMESPACE_VERSION  |
46 |   |
47 | /**  |
48 | * @defgroup mutexes Mutexes  |
49 | * @ingroup concurrency  |
50 | *  |
51 | * Classes for mutex support.  |
52 | * @{  |
53 | */  |
54 |   |
55 | #ifdef _GLIBCXX_HAS_GTHREADS  |
56 | // Common base class for std::mutex and std::timed_mutex  |
57 | class __mutex_base  |
58 | {  |
59 | protected:  |
60 | typedef __gthread_mutex_t __native_type;  |
61 |   |
62 | #ifdef __GTHREAD_MUTEX_INIT  |
63 | __native_type _M_mutex = __GTHREAD_MUTEX_INIT;  |
64 |   |
65 | constexpr __mutex_base() noexcept = default;  |
66 | #else  |
67 | __native_type _M_mutex;  |
68 |   |
69 | __mutex_base() noexcept  |
70 | {  |
71 | // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)  |
72 | __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);  |
73 | }  |
74 |   |
75 | ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }  |
76 | #endif  |
77 |   |
78 | __mutex_base(const __mutex_base&) = delete;  |
79 | __mutex_base& operator=(const __mutex_base&) = delete;  |
80 | };  |
81 |   |
82 | /// The standard mutex type.  |
83 | class mutex : private __mutex_base  |
84 | {  |
85 | public:  |
86 | typedef __native_type* native_handle_type;  |
87 |   |
88 | #ifdef __GTHREAD_MUTEX_INIT  |
89 | constexpr  |
90 | #endif  |
91 | mutex() noexcept = default;  |
92 | ~mutex() = default;  |
93 |   |
94 | mutex(const mutex&) = delete;  |
95 | mutex& operator=(const mutex&) = delete;  |
96 |   |
97 | void  |
98 | lock()  |
99 | {  |
100 | int __e = __gthread_mutex_lock(&_M_mutex);  |
101 |   |
102 | // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)  |
103 | if (__e)  |
104 | __throw_system_error(__e);  |
105 | }  |
106 |   |
107 | bool  |
108 | try_lock() noexcept  |
109 | {  |
110 | // XXX EINVAL, EAGAIN, EBUSY  |
111 | return !__gthread_mutex_trylock(&_M_mutex);  |
112 | }  |
113 |   |
114 | void  |
115 | unlock()  |
116 | {  |
117 | // XXX EINVAL, EAGAIN, EPERM  |
118 | __gthread_mutex_unlock(&_M_mutex);  |
119 | }  |
120 |   |
121 | native_handle_type  |
122 | native_handle() noexcept  |
123 | { return &_M_mutex; }  |
124 | };  |
125 |   |
126 | #endif // _GLIBCXX_HAS_GTHREADS  |
127 |   |
128 | /// Do not acquire ownership of the mutex.  |
129 | struct defer_lock_t { explicit defer_lock_t() = default; };  |
130 |   |
131 | /// Try to acquire ownership of the mutex without blocking.  |
132 | struct try_to_lock_t { explicit try_to_lock_t() = default; };  |
133 |   |
134 | /// Assume the calling thread has already obtained mutex ownership  |
135 | /// and manage it.  |
136 | struct adopt_lock_t { explicit adopt_lock_t() = default; };  |
137 |   |
138 | /// Tag used to prevent a scoped lock from acquiring ownership of a mutex.  |
139 | _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { };  |
140 |   |
141 | /// Tag used to prevent a scoped lock from blocking if a mutex is locked.  |
142 | _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { };  |
143 |   |
144 | /// Tag used to make a scoped lock take ownership of a locked mutex.  |
145 | _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { };  |
146 |   |
147 | /** @brief A simple scoped lock type.  |
148 | *  |
149 | * A lock_guard controls mutex ownership within a scope, releasing  |
150 | * ownership in the destructor.  |
151 | */  |
152 | template<typename _Mutex>  |
153 | class lock_guard  |
154 | {  |
155 | public:  |
156 | typedef _Mutex mutex_type;  |
157 |   |
158 | explicit lock_guard(mutex_type& __m) : _M_device(__m)  |
159 | { _M_device.lock(); }  |
160 |   |
161 | lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m)  |
162 | { } // calling thread owns mutex  |
163 |   |
164 | ~lock_guard()  |
165 | { _M_device.unlock(); }  |
166 |   |
167 | lock_guard(const lock_guard&) = delete;  |
168 | lock_guard& operator=(const lock_guard&) = delete;  |
169 |   |
170 | private:  |
171 | mutex_type& _M_device;  |
172 | };  |
173 |   |
174 | // @} group mutexes  |
175 | _GLIBCXX_END_NAMESPACE_VERSION  |
176 | } // namespace  |
177 | #endif // C++11  |
178 | #endif // _GLIBCXX_MUTEX_H  |
179 | |