Line data Source code
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 0 : 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 0 : mutex() noexcept = default; 92 : ~mutex() = default; 93 : 94 : mutex(const mutex&) = delete; 95 : mutex& operator=(const mutex&) = delete; 96 : 97 : void 98 712 : lock() 99 : { 100 712 : int __e = __gthread_mutex_lock(&_M_mutex); 101 : 102 : // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 103 712 : if (__e) 104 0 : __throw_system_error(__e); 105 712 : } 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 712 : unlock() 116 : { 117 : // XXX EINVAL, EAGAIN, EPERM 118 712 : __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 0 : explicit lock_guard(mutex_type& __m) : _M_device(__m) 159 0 : { _M_device.lock(); } 160 : 161 : lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) 162 : { } // calling thread owns mutex 163 : 164 0 : ~lock_guard() 165 0 : { _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