Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/ext/concurrence.h
1 // Support for concurrent programing -*- C++ -*- 2 3 // Copyright (C) 2003-2025 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 ext/concurrence.h 26 * This file is a GNU extension to the Standard C++ Library. 27 */ 28 29 #ifndef _CONCURRENCE_H 30 #define _CONCURRENCE_H 1 31 32 #ifdef _GLIBCXX_SYSHDR 33 #pragma GCC system_header 34 #endif 35 36 #include <exception> 37 #include <bits/gthr.h> 38 #include <bits/functexcept.h> 39 #include <bits/cpp_type_traits.h> 40 #include <ext/type_traits.h> 41 42 #pragma GCC diagnostic push 43 #pragma GCC diagnostic ignored "-Wc++11-extensions" 44 45 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 46 { 47 _GLIBCXX_BEGIN_NAMESPACE_VERSION 48 49 // Available locking policies: 50 // _S_single single-threaded code that doesn't need to be locked. 51 // _S_mutex multi-threaded code that requires additional support 52 // from gthr.h or abstraction layers in concurrence.h. 53 // _S_atomic multi-threaded code using atomic operations. 54 enum _Lock_policy { _S_single, _S_mutex, _S_atomic }; 55 56 // Compile time constant that indicates prefered locking policy in 57 // the current configuration. 58 _GLIBCXX17_INLINE const _Lock_policy __default_lock_policy = 59 #ifndef __GTHREADS 60 _S_single; 61 #elif defined _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY 62 _S_atomic; 63 #else 64 _S_mutex; 65 #endif 66 67 // NB: As this is used in libsupc++, need to only depend on 68 // exception. No stdexception classes, no use of std::string. 69 class __concurrence_lock_error : public std::exception 70 { 71 public: 72 virtual char const* 73 what() const throw() 74 { return "__gnu_cxx::__concurrence_lock_error"; } 75 }; 76 77 class __concurrence_unlock_error : public std::exception 78 { 79 public: 80 virtual char const* 81 what() const throw() 82 { return "__gnu_cxx::__concurrence_unlock_error"; } 83 }; 84 85 class __concurrence_broadcast_error : public std::exception 86 { 87 public: 88 virtual char const* 89 what() const throw() 90 { return "__gnu_cxx::__concurrence_broadcast_error"; } 91 }; 92 93 class __concurrence_wait_error : public std::exception 94 { 95 public: 96 virtual char const* 97 what() const throw() 98 { return "__gnu_cxx::__concurrence_wait_error"; } 99 }; 100 101 // Substitute for concurrence_error object in the case of -fno-exceptions. 102 inline void 103 __throw_concurrence_lock_error() 104 { _GLIBCXX_THROW_OR_ABORT(__concurrence_lock_error()); } 105 106 inline void 107 __throw_concurrence_unlock_error() 108 { _GLIBCXX_THROW_OR_ABORT(__concurrence_unlock_error()); } 109 110 #ifdef __GTHREAD_HAS_COND 111 inline void 112 __throw_concurrence_broadcast_error() 113 { _GLIBCXX_THROW_OR_ABORT(__concurrence_broadcast_error()); } 114 115 inline void 116 __throw_concurrence_wait_error() 117 { _GLIBCXX_THROW_OR_ABORT(__concurrence_wait_error()); } 118 #endif 119 120 class __mutex 121 { 122 private: 123 #if __GTHREADS && defined __GTHREAD_MUTEX_INIT 124 __gthread_mutex_t _M_mutex = __GTHREAD_MUTEX_INIT; 125 #else 126 __gthread_mutex_t _M_mutex; 127 #endif 128 129 __mutex(const __mutex&); 130 __mutex& operator=(const __mutex&); 131 132 public: 133 __mutex() 134 { 135 #if __GTHREADS && ! defined __GTHREAD_MUTEX_INIT 136 if (__gthread_active_p()) 137 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); 138 #endif 139 } 140 141 #if __GTHREADS && ! defined __GTHREAD_MUTEX_INIT 142 ~__mutex() 143 { 144 if (__gthread_active_p()) 145 __gthread_mutex_destroy(&_M_mutex); 146 } 147 #endif 148 149 void lock() 150 { 151 #if __GTHREADS 152 if (__gthread_active_p()) 153 { 154 if (__gthread_mutex_lock(&_M_mutex) != 0) 155 __throw_concurrence_lock_error(); 156 } 157 #endif 158 } 159 160 void unlock() 161 { 162 #if __GTHREADS 163 if (__gthread_active_p()) 164 { 165 if (__gthread_mutex_unlock(&_M_mutex) != 0) 166 __throw_concurrence_unlock_error(); 167 } 168 #endif 169 } 170 171 __gthread_mutex_t* gthread_mutex(void) 172 { return &_M_mutex; } 173 }; 174 175 class __recursive_mutex 176 { 177 private: 178 #if __GTHREADS && defined __GTHREAD_RECURSIVE_MUTEX_INIT 179 __gthread_recursive_mutex_t _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; 180 #else 181 __gthread_recursive_mutex_t _M_mutex; 182 #endif 183 184 __recursive_mutex(const __recursive_mutex&); 185 __recursive_mutex& operator=(const __recursive_mutex&); 186 187 public: 188 __recursive_mutex() 189 { 190 #if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT 191 if (__gthread_active_p()) 192 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 193 #endif 194 } 195 196 #if __GTHREADS && ! defined __GTHREAD_RECURSIVE_MUTEX_INIT 197 ~__recursive_mutex() 198 { 199 if (__gthread_active_p()) 200 __gthread_recursive_mutex_destroy(&_M_mutex); 201 } 202 #endif 203 204 void lock() 205 { 206 #if __GTHREADS 207 if (__gthread_active_p()) 208 { 209 if (__gthread_recursive_mutex_lock(&_M_mutex) != 0) 210 __throw_concurrence_lock_error(); 211 } 212 #endif 213 } 214 215 void unlock() 216 { 217 #if __GTHREADS 218 if (__gthread_active_p()) 219 { 220 if (__gthread_recursive_mutex_unlock(&_M_mutex) != 0) 221 __throw_concurrence_unlock_error(); 222 } 223 #endif 224 } 225 226 __gthread_recursive_mutex_t* gthread_recursive_mutex(void) 227 { return &_M_mutex; } 228 }; 229 230 /// Scoped lock idiom. 231 // Acquire the mutex here with a constructor call, then release with 232 // the destructor call in accordance with RAII style. 233 class __scoped_lock 234 { 235 public: 236 typedef __mutex __mutex_type; 237 238 private: 239 __mutex_type& _M_device; 240 241 __scoped_lock(const __scoped_lock&); 242 __scoped_lock& operator=(const __scoped_lock&); 243 244 public: 245 explicit __scoped_lock(__mutex_type& __name) : _M_device(__name) 246 { _M_device.lock(); } 247 248 ~__scoped_lock() throw() 249 { _M_device.unlock(); } 250 }; 251 252 #ifdef __GTHREAD_HAS_COND 253 class __cond 254 { 255 private: 256 #if __GTHREADS && defined __GTHREAD_COND_INIT 257 __gthread_cond_t _M_cond = __GTHREAD_COND_INIT; 258 #else 259 __gthread_cond_t _M_cond; 260 #endif 261 262 __cond(const __cond&); 263 __cond& operator=(const __cond&); 264 265 public: 266 __cond() 267 { 268 #if __GTHREADS && ! defined __GTHREAD_COND_INIT 269 if (__gthread_active_p()) 270 __GTHREAD_COND_INIT_FUNCTION(&_M_cond); 271 #endif 272 } 273 274 #if __GTHREADS && ! defined __GTHREAD_COND_INIT 275 ~__cond() 276 { 277 if (__gthread_active_p()) 278 __gthread_cond_destroy(&_M_cond); 279 } 280 #endif 281 282 void broadcast() 283 { 284 #if __GTHREADS 285 if (__gthread_active_p()) 286 { 287 if (__gthread_cond_broadcast(&_M_cond) != 0) 288 __throw_concurrence_broadcast_error(); 289 } 290 #endif 291 } 292 293 void wait(__mutex *mutex) 294 { 295 #if __GTHREADS 296 { 297 if (__gthread_cond_wait(&_M_cond, mutex->gthread_mutex()) != 0) 298 __throw_concurrence_wait_error(); 299 } 300 #endif 301 } 302 303 void wait_recursive(__recursive_mutex *mutex) 304 { 305 #if __GTHREADS 306 { 307 if (__gthread_cond_wait_recursive(&_M_cond, 308 mutex->gthread_recursive_mutex()) 309 != 0) 310 __throw_concurrence_wait_error(); 311 } 312 #endif 313 } 314 }; 315 #endif 316 317 _GLIBCXX_END_NAMESPACE_VERSION 318 } // namespace 319 320 #pragma GCC diagnostic pop 321 322 #endif