Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/11/bits/semaphore_base.h
$ cat -n /usr/include/c++/11/bits/semaphore_base.h 1 // -*- C++ -*- header. 2 3 // Copyright (C) 2020-2021 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 //
. 24 25 /** @file bits/semaphore_base.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{semaphore} 28 */ 29 30 #ifndef _GLIBCXX_SEMAPHORE_BASE_H 31 #define _GLIBCXX_SEMAPHORE_BASE_H 1 32 33 #pragma GCC system_header 34 35 #include
36 #if __cpp_lib_atomic_wait 37 #include
38 #include
39 #endif // __cpp_lib_atomic_wait 40 41 #ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE 42 # include
// std::terminate 43 # include
// errno, EINTR, EAGAIN etc. 44 # include
// SEM_VALUE_MAX 45 # include
// sem_t, sem_init, sem_wait, sem_post etc. 46 #endif 47 48 #include
49 #include
50 51 namespace std _GLIBCXX_VISIBILITY(default) 52 { 53 _GLIBCXX_BEGIN_NAMESPACE_VERSION 54 55 #ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE 56 struct __platform_semaphore 57 { 58 using __clock_t = chrono::system_clock; 59 #ifdef SEM_VALUE_MAX 60 static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX; 61 #else 62 static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX; 63 #endif 64 65 explicit __platform_semaphore(ptrdiff_t __count) noexcept 66 { 67 sem_init(&_M_semaphore, 0, __count); 68 } 69 70 __platform_semaphore(const __platform_semaphore&) = delete; 71 __platform_semaphore& operator=(const __platform_semaphore&) = delete; 72 73 ~__platform_semaphore() 74 { sem_destroy(&_M_semaphore); } 75 76 _GLIBCXX_ALWAYS_INLINE void 77 _M_acquire() noexcept 78 { 79 for (;;) 80 { 81 auto __err = sem_wait(&_M_semaphore); 82 if (__err && (errno == EINTR)) 83 continue; 84 else if (__err) 85 std::terminate(); 86 else 87 break; 88 } 89 } 90 91 _GLIBCXX_ALWAYS_INLINE bool 92 _M_try_acquire() noexcept 93 { 94 for (;;) 95 { 96 auto __err = sem_trywait(&_M_semaphore); 97 if (__err && (errno == EINTR)) 98 continue; 99 else if (__err && (errno == EAGAIN)) 100 return false; 101 else if (__err) 102 std::terminate(); 103 else 104 break; 105 } 106 return true; 107 } 108 109 _GLIBCXX_ALWAYS_INLINE void 110 _M_release(std::ptrdiff_t __update) noexcept 111 { 112 for(; __update != 0; --__update) 113 { 114 auto __err = sem_post(&_M_semaphore); 115 if (__err) 116 std::terminate(); 117 } 118 } 119 120 bool 121 _M_try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime) 122 noexcept 123 { 124 125 auto __s = chrono::time_point_cast
(__atime); 126 auto __ns = chrono::duration_cast
(__atime - __s); 127 128 struct timespec __ts = 129 { 130 static_cast
(__s.time_since_epoch().count()), 131 static_cast
(__ns.count()) 132 }; 133 134 for (;;) 135 { 136 if (auto __err = sem_timedwait(&_M_semaphore, &__ts)) 137 { 138 if (errno == EINTR) 139 continue; 140 else if (errno == ETIMEDOUT || errno == EINVAL) 141 return false; 142 else 143 std::terminate(); 144 } 145 else 146 break; 147 } 148 return true; 149 } 150 151 template
152 bool 153 _M_try_acquire_until(const chrono::time_point<_Clock, 154 _Duration>& __atime) noexcept 155 { 156 if constexpr (std::is_same_v<__clock_t, _Clock>) 157 { 158 return _M_try_acquire_until_impl(__atime); 159 } 160 else 161 { 162 const typename _Clock::time_point __c_entry = _Clock::now(); 163 const auto __s_entry = __clock_t::now(); 164 const auto __delta = __atime - __c_entry; 165 const auto __s_atime = __s_entry + __delta; 166 if (_M_try_acquire_until_impl(__s_atime)) 167 return true; 168 169 // We got a timeout when measured against __clock_t but 170 // we need to check against the caller-supplied clock 171 // to tell whether we should return a timeout. 172 return (_Clock::now() < __atime); 173 } 174 } 175 176 template
177 _GLIBCXX_ALWAYS_INLINE bool 178 _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) 179 noexcept 180 { return _M_try_acquire_until(__clock_t::now() + __rtime); } 181 182 private: 183 sem_t _M_semaphore; 184 }; 185 #endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE 186 187 #if __cpp_lib_atomic_wait 188 struct __atomic_semaphore 189 { 190 static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits
::__max; 191 explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept 192 : _M_counter(__count) 193 { 194 __glibcxx_assert(__count >= 0 && __count <= _S_max); 195 } 196 197 __atomic_semaphore(const __atomic_semaphore&) = delete; 198 __atomic_semaphore& operator=(const __atomic_semaphore&) = delete; 199 200 static _GLIBCXX_ALWAYS_INLINE bool 201 _S_do_try_acquire(__detail::__platform_wait_t* __counter) noexcept 202 { 203 auto __old = __atomic_impl::load(__counter, memory_order::acquire); 204 if (__old == 0) 205 return false; 206 207 return __atomic_impl::compare_exchange_strong(__counter, 208 __old, __old - 1, 209 memory_order::acquire, 210 memory_order::relaxed); 211 } 212 213 _GLIBCXX_ALWAYS_INLINE void 214 _M_acquire() noexcept 215 { 216 auto const __pred = 217 [this] { return _S_do_try_acquire(&this->_M_counter); }; 218 std::__atomic_wait_address_bare(&_M_counter, __pred); 219 } 220 221 bool 222 _M_try_acquire() noexcept 223 { 224 auto const __pred = 225 [this] { return _S_do_try_acquire(&this->_M_counter); }; 226 return std::__detail::__atomic_spin(__pred); 227 } 228 229 template
230 _GLIBCXX_ALWAYS_INLINE bool 231 _M_try_acquire_until(const chrono::time_point<_Clock, 232 _Duration>& __atime) noexcept 233 { 234 auto const __pred = 235 [this] { return _S_do_try_acquire(&this->_M_counter); }; 236 237 return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime); 238 } 239 240 template
241 _GLIBCXX_ALWAYS_INLINE bool 242 _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) 243 noexcept 244 { 245 auto const __pred = 246 [this] { return _S_do_try_acquire(&this->_M_counter); }; 247 248 return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime); 249 } 250 251 _GLIBCXX_ALWAYS_INLINE void 252 _M_release(ptrdiff_t __update) noexcept 253 { 254 if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release)) 255 return; 256 if (__update > 1) 257 __atomic_notify_address_bare(&_M_counter, true); 258 else 259 __atomic_notify_address_bare(&_M_counter, true); 260 // FIXME - Figure out why this does not wake a waiting thread 261 // __atomic_notify_address_bare(&_M_counter, false); 262 } 263 264 private: 265 alignas(__detail::__platform_wait_alignment) 266 __detail::__platform_wait_t _M_counter; 267 }; 268 #endif // __cpp_lib_atomic_wait 269 270 // Note: the _GLIBCXX_USE_POSIX_SEMAPHORE macro can be used to force the 271 // use of Posix semaphores (sem_t). Doing so however, alters the ABI. 272 #if defined __cpp_lib_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE 273 using __semaphore_impl = __atomic_semaphore; 274 #elif _GLIBCXX_HAVE_POSIX_SEMAPHORE 275 using __semaphore_impl = __platform_semaphore; 276 #endif 277 278 _GLIBCXX_END_NAMESPACE_VERSION 279 } // namespace std 280 #endif // _GLIBCXX_SEMAPHORE_BASE_H
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™