/
usr
/
include
/
c++
/
11
/
/usr/include/c++/11
mkdir
upload
Name
Size
Mode
Actions
backward/
-
0755
rm
bits/
-
0755
rm
debug/
-
0755
rm
decimal/
-
0755
rm
experimental/
-
0755
rm
ext/
-
0755
rm
parallel/
-
0755
rm
pstl/
-
0755
rm
tr1/
-
0755
rm
tr2/
-
0755
rm
algorithm
3045
0644
edit
dl
rm
any
18758
0644
edit
dl
rm
array
13820
0644
edit
dl
rm
atomic
48800
0644
edit
dl
rm
barrier
8026
0644
edit
dl
rm
bit
12187
0644
edit
dl
rm
bitset
45995
0644
edit
dl
rm
cassert
1648
0644
edit
dl
rm
ccomplex
1335
0644
edit
dl
rm
cctype
2409
0644
edit
dl
rm
cerrno
1770
0644
edit
dl
rm
cfenv
2051
0644
edit
dl
rm
cfloat
1889
0644
edit
dl
rm
charconv
19761
0644
edit
dl
rm
chrono
97212
0644
edit
dl
rm
cinttypes
2157
0644
edit
dl
rm
ciso646
1464
0644
edit
dl
rm
climits
1913
0644
edit
dl
rm
clocale
1905
0644
edit
dl
rm
cmath
49382
0644
edit
dl
rm
codecvt
5275
0644
edit
dl
rm
compare
28271
0644
edit
dl
rm
complex
56703
0644
edit
dl
rm
complex.h
1596
0644
edit
dl
rm
concepts
12230
0644
edit
dl
rm
condition_variable
12780
0644
edit
dl
rm
coroutine
9156
0644
edit
dl
rm
csetjmp
1949
0644
edit
dl
rm
csignal
1855
0644
edit
dl
rm
cstdalign
1407
0644
edit
dl
rm
cstdarg
1868
0644
edit
dl
rm
cstdbool
1401
0644
edit
dl
rm
cstddef
6690
0644
edit
dl
rm
cstdint
2335
0644
edit
dl
rm
cstdio
4439
0644
edit
dl
rm
cstdlib
6325
0644
edit
dl
rm
cstring
3156
0644
edit
dl
rm
ctgmath
1360
0644
edit
dl
rm
ctime
2298
0644
edit
dl
rm
cuchar
2210
0644
edit
dl
rm
cwchar
6542
0644
edit
dl
rm
cwctype
2793
0644
edit
dl
rm
cxxabi.h
22280
0644
edit
dl
rm
deque
3973
0644
edit
dl
rm
exception
5017
0644
edit
dl
rm
execution
1803
0644
edit
dl
rm
fenv.h
2020
0644
edit
dl
rm
filesystem
1645
0644
edit
dl
rm
forward_list
2690
0644
edit
dl
rm
fstream
40680
0644
edit
dl
rm
functional
40200
0644
edit
dl
rm
future
52278
0644
edit
dl
rm
initializer_list
3038
0644
edit
dl
rm
iomanip
16547
0644
edit
dl
rm
ios
1601
0644
edit
dl
rm
iosfwd
7513
0644
edit
dl
rm
iostream
2697
0644
edit
dl
rm
istream
34098
0644
edit
dl
rm
iterator
2751
0644
edit
dl
rm
latch
2732
0644
edit
dl
rm
limits
71674
0644
edit
dl
rm
list
3657
0644
edit
dl
rm
locale
1488
0644
edit
dl
rm
map
3929
0644
edit
dl
rm
math.h
4573
0644
edit
dl
rm
memory
4513
0644
edit
dl
rm
memory_resource
21113
0644
edit
dl
rm
mutex
24223
0644
edit
dl
rm
new
8349
0644
edit
dl
rm
numbers
6244
0644
edit
dl
rm
numeric
26110
0644
edit
dl
rm
optional
40170
0644
edit
dl
rm
ostream
25976
0644
edit
dl
rm
queue
2467
0644
edit
dl
rm
random
1692
0644
edit
dl
rm
ranges
107201
0644
edit
dl
rm
ratio
20108
0644
edit
dl
rm
regex
2861
0644
edit
dl
rm
scoped_allocator
17649
0644
edit
dl
rm
semaphore
3000
0644
edit
dl
rm
set
3799
0644
edit
dl
rm
shared_mutex
24588
0644
edit
dl
rm
source_location
2747
0644
edit
dl
rm
span
13131
0644
edit
dl
rm
sstream
39231
0644
edit
dl
rm
stack
2391
0644
edit
dl
rm
stdexcept
9878
0644
edit
dl
rm
stdlib.h
2248
0644
edit
dl
rm
stop_token
15982
0644
edit
dl
rm
streambuf
29890
0644
edit
dl
rm
string
4645
0644
edit
dl
rm
string_view
26157
0644
edit
dl
rm
syncstream
8330
0644
edit
dl
rm
system_error
15006
0644
edit
dl
rm
tgmath.h
1360
0644
edit
dl
rm
thread
5919
0644
edit
dl
rm
tuple
62767
0644
edit
dl
rm
typeindex
3512
0644
edit
dl
rm
typeinfo
7746
0644
edit
dl
rm
type_traits
107667
0644
edit
dl
rm
unordered_map
3467
0644
edit
dl
rm
unordered_set
3340
0644
edit
dl
rm
utility
14816
0644
edit
dl
rm
valarray
40695
0644
edit
dl
rm
variant
62866
0644
edit
dl
rm
vector
4275
0644
edit
dl
rm
version
9264
0644
edit
dl
rm
Edit:
/usr/include/c++/11/stop_token
(15982B)
// <stop_token> -*- C++ -*- // Copyright (C) 2019-2021 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. /** @file include/stop_token * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_STOP_TOKEN #define _GLIBCXX_STOP_TOKEN #if __cplusplus > 201703L #include <atomic> #include <bits/std_thread.h> #include <semaphore> #define __cpp_lib_jthread 201911L namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Tag type indicating a stop_source should have no shared-stop-state. struct nostopstate_t { explicit nostopstate_t() = default; }; inline constexpr nostopstate_t nostopstate{}; class stop_source; /// Allow testing whether a stop request has been made on a `stop_source`. class stop_token { public: stop_token() noexcept = default; stop_token(const stop_token&) noexcept = default; stop_token(stop_token&&) noexcept = default; ~stop_token() = default; stop_token& operator=(const stop_token&) noexcept = default; stop_token& operator=(stop_token&&) noexcept = default; [[nodiscard]] bool stop_possible() const noexcept { return static_cast<bool>(_M_state) && _M_state->_M_stop_possible(); } [[nodiscard]] bool stop_requested() const noexcept { return static_cast<bool>(_M_state) && _M_state->_M_stop_requested(); } void swap(stop_token& __rhs) noexcept { _M_state.swap(__rhs._M_state); } [[nodiscard]] friend bool operator==(const stop_token& __a, const stop_token& __b) { return __a._M_state == __b._M_state; } friend void swap(stop_token& __lhs, stop_token& __rhs) noexcept { __lhs.swap(__rhs); } private: friend class stop_source; template<typename _Callback> friend class stop_callback; static void _S_yield() noexcept { #if defined __i386__ || defined __x86_64__ __builtin_ia32_pause(); #endif this_thread::yield(); } #ifndef __cpp_lib_semaphore struct binary_semaphore { explicit binary_semaphore(int __d) : _M_counter(__d > 0) { } void release() { _M_counter.fetch_add(1, memory_order::release); } void acquire() { int __old = 1; while (!_M_counter.compare_exchange_weak(__old, 0, memory_order::acquire, memory_order::relaxed)) { __old = 1; _S_yield(); } } atomic<int> _M_counter; }; #endif struct _Stop_cb { using __cb_type = void(_Stop_cb*) noexcept; __cb_type* _M_callback; _Stop_cb* _M_prev = nullptr; _Stop_cb* _M_next = nullptr; bool* _M_destroyed = nullptr; binary_semaphore _M_done{0}; [[__gnu__::__nonnull__]] explicit _Stop_cb(__cb_type* __cb) : _M_callback(__cb) { } void _M_run() noexcept { _M_callback(this); } }; struct _Stop_state_t { using value_type = uint32_t; static constexpr value_type _S_stop_requested_bit = 1; static constexpr value_type _S_locked_bit = 2; static constexpr value_type _S_ssrc_counter_inc = 4; std::atomic<value_type> _M_owners{1}; std::atomic<value_type> _M_value{_S_ssrc_counter_inc}; _Stop_cb* _M_head = nullptr; std::thread::id _M_requester; _Stop_state_t() = default; bool _M_stop_possible() noexcept { // true if a stop request has already been made or there are still // stop_source objects that would allow one to be made. return _M_value.load(memory_order::acquire) & ~_S_locked_bit; } bool _M_stop_requested() noexcept { return _M_value.load(memory_order::acquire) & _S_stop_requested_bit; } void _M_add_owner() noexcept { _M_owners.fetch_add(1, memory_order::relaxed); } void _M_release_ownership() noexcept { if (_M_owners.fetch_sub(1, memory_order::acq_rel) == 1) delete this; } void _M_add_ssrc() noexcept { _M_value.fetch_add(_S_ssrc_counter_inc, memory_order::relaxed); } void _M_sub_ssrc() noexcept { _M_value.fetch_sub(_S_ssrc_counter_inc, memory_order::release); } // Obtain lock. void _M_lock() noexcept { // Can use relaxed loads to get the current value. // The successful call to _M_try_lock is an acquire operation. auto __old = _M_value.load(memory_order::relaxed); while (!_M_try_lock(__old, memory_order::relaxed)) { } } // Precondition: calling thread holds the lock. void _M_unlock() noexcept { _M_value.fetch_sub(_S_locked_bit, memory_order::release); } bool _M_request_stop() noexcept { // obtain lock and set stop_requested bit auto __old = _M_value.load(memory_order::acquire); do { if (__old & _S_stop_requested_bit) // stop request already made return false; } while (!_M_try_lock_and_stop(__old)); _M_requester = this_thread::get_id(); while (_M_head) { bool __last_cb; _Stop_cb* __cb = _M_head; _M_head = _M_head->_M_next; if (_M_head) { _M_head->_M_prev = nullptr; __last_cb = false; } else __last_cb = true; // Allow other callbacks to be unregistered while __cb runs. _M_unlock(); bool __destroyed = false; __cb->_M_destroyed = &__destroyed; // run callback __cb->_M_run(); if (!__destroyed) { __cb->_M_destroyed = nullptr; // synchronize with destructor of stop_callback that owns *__cb if (!__gnu_cxx::__is_single_threaded()) __cb->_M_done.release(); } // Avoid relocking if we already know there are no more callbacks. if (__last_cb) return true; _M_lock(); } _M_unlock(); return true; } [[__gnu__::__nonnull__]] bool _M_register_callback(_Stop_cb* __cb) noexcept { auto __old = _M_value.load(memory_order::acquire); do { if (__old & _S_stop_requested_bit) // stop request already made { __cb->_M_run(); // run synchronously return false; } if (__old < _S_ssrc_counter_inc) // no stop_source owns *this // No need to register callback if no stop request can be made. // Returning false also means the stop_callback does not share // ownership of this state, but that's not observable. return false; } while (!_M_try_lock(__old)); __cb->_M_next = _M_head; if (_M_head) { _M_head->_M_prev = __cb; } _M_head = __cb; _M_unlock(); return true; } // Called by ~stop_callback just before destroying *__cb. [[__gnu__::__nonnull__]] void _M_remove_callback(_Stop_cb* __cb) { _M_lock(); if (__cb == _M_head) { _M_head = _M_head->_M_next; if (_M_head) _M_head->_M_prev = nullptr; _M_unlock(); return; } else if (__cb->_M_prev) { __cb->_M_prev->_M_next = __cb->_M_next; if (__cb->_M_next) __cb->_M_next->_M_prev = __cb->_M_prev; _M_unlock(); return; } _M_unlock(); // Callback is not in the list, so must have been removed by a call to // _M_request_stop. // Despite appearances there is no data race on _M_requester. The only // write to it happens before the callback is removed from the list, // and removing it from the list happens before this read. if (!(_M_requester == this_thread::get_id())) { // Synchronize with completion of callback. __cb->_M_done.acquire(); // Safe for ~stop_callback to destroy *__cb now. return; } if (__cb->_M_destroyed) *__cb->_M_destroyed = true; } // Try to obtain the lock. // Returns true if the lock is acquired (with memory order acquire). // Otherwise, sets __curval = _M_value.load(__failure) and returns false. // Might fail spuriously, so must be called in a loop. bool _M_try_lock(value_type& __curval, memory_order __failure = memory_order::acquire) noexcept { return _M_do_try_lock(__curval, 0, memory_order::acquire, __failure); } // Try to obtain the lock to make a stop request. // Returns true if the lock is acquired and the _S_stop_requested_bit is // set (with memory order acq_rel so that other threads see the request). // Otherwise, sets __curval = _M_value.load(memory_order::acquire) and // returns false. // Might fail spuriously, so must be called in a loop. bool _M_try_lock_and_stop(value_type& __curval) noexcept { return _M_do_try_lock(__curval, _S_stop_requested_bit, memory_order::acq_rel, memory_order::acquire); } bool _M_do_try_lock(value_type& __curval, value_type __newbits, memory_order __success, memory_order __failure) noexcept { if (__curval & _S_locked_bit) { _S_yield(); __curval = _M_value.load(__failure); return false; } __newbits |= _S_locked_bit; return _M_value.compare_exchange_weak(__curval, __curval | __newbits, __success, __failure); } }; struct _Stop_state_ref { _Stop_state_ref() = default; explicit _Stop_state_ref(const stop_source&) : _M_ptr(new _Stop_state_t()) { } _Stop_state_ref(const _Stop_state_ref& __other) noexcept : _M_ptr(__other._M_ptr) { if (_M_ptr) _M_ptr->_M_add_owner(); } _Stop_state_ref(_Stop_state_ref&& __other) noexcept : _M_ptr(__other._M_ptr) { __other._M_ptr = nullptr; } _Stop_state_ref& operator=(const _Stop_state_ref& __other) noexcept { if (auto __ptr = __other._M_ptr; __ptr != _M_ptr) { if (__ptr) __ptr->_M_add_owner(); if (_M_ptr) _M_ptr->_M_release_ownership(); _M_ptr = __ptr; } return *this; } _Stop_state_ref& operator=(_Stop_state_ref&& __other) noexcept { _Stop_state_ref(std::move(__other)).swap(*this); return *this; } ~_Stop_state_ref() { if (_M_ptr) _M_ptr->_M_release_ownership(); } void swap(_Stop_state_ref& __other) noexcept { std::swap(_M_ptr, __other._M_ptr); } explicit operator bool() const noexcept { return _M_ptr != nullptr; } _Stop_state_t* operator->() const noexcept { return _M_ptr; } #if __cpp_impl_three_way_comparison >= 201907L friend bool operator==(const _Stop_state_ref&, const _Stop_state_ref&) = default; #else friend bool operator==(const _Stop_state_ref& __lhs, const _Stop_state_ref& __rhs) noexcept { return __lhs._M_ptr == __rhs._M_ptr; } friend bool operator!=(const _Stop_state_ref& __lhs, const _Stop_state_ref& __rhs) noexcept { return __lhs._M_ptr != __rhs._M_ptr; } #endif private: _Stop_state_t* _M_ptr = nullptr; }; _Stop_state_ref _M_state; explicit stop_token(const _Stop_state_ref& __state) noexcept : _M_state{__state} { } }; /// A type that allows a stop request to be made. class stop_source { public: stop_source() : _M_state(*this) { } explicit stop_source(std::nostopstate_t) noexcept { } stop_source(const stop_source& __other) noexcept : _M_state(__other._M_state) { if (_M_state) _M_state->_M_add_ssrc(); } stop_source(stop_source&&) noexcept = default; stop_source& operator=(const stop_source& __other) noexcept { if (_M_state != __other._M_state) { stop_source __sink(std::move(*this)); _M_state = __other._M_state; if (_M_state) _M_state->_M_add_ssrc(); } return *this; } stop_source& operator=(stop_source&&) noexcept = default; ~stop_source() { if (_M_state) _M_state->_M_sub_ssrc(); } [[nodiscard]] bool stop_possible() const noexcept { return static_cast<bool>(_M_state); } [[nodiscard]] bool stop_requested() const noexcept { return static_cast<bool>(_M_state) && _M_state->_M_stop_requested(); } bool request_stop() const noexcept { if (stop_possible()) return _M_state->_M_request_stop(); return false; } [[nodiscard]] stop_token get_token() const noexcept { return stop_token{_M_state}; } void swap(stop_source& __other) noexcept { _M_state.swap(__other._M_state); } [[nodiscard]] friend bool operator==(const stop_source& __a, const stop_source& __b) noexcept { return __a._M_state == __b._M_state; } friend void swap(stop_source& __lhs, stop_source& __rhs) noexcept { __lhs.swap(__rhs); } private: stop_token::_Stop_state_ref _M_state; }; /// A wrapper for callbacks to be run when a stop request is made. template<typename _Callback> class [[nodiscard]] stop_callback { static_assert(is_nothrow_destructible_v<_Callback>); static_assert(is_invocable_v<_Callback>); public: using callback_type = _Callback; template<typename _Cb, enable_if_t<is_constructible_v<_Callback, _Cb>, int> = 0> explicit stop_callback(const stop_token& __token, _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>) : _M_cb(std::forward<_Cb>(__cb)) { if (auto __state = __token._M_state) { if (__state->_M_register_callback(&_M_cb)) _M_state.swap(__state); } } template<typename _Cb, enable_if_t<is_constructible_v<_Callback, _Cb>, int> = 0> explicit stop_callback(stop_token&& __token, _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>) : _M_cb(std::forward<_Cb>(__cb)) { if (auto& __state = __token._M_state) { if (__state->_M_register_callback(&_M_cb)) _M_state.swap(__state); } } ~stop_callback() { if (_M_state) { _M_state->_M_remove_callback(&_M_cb); } } stop_callback(const stop_callback&) = delete; stop_callback& operator=(const stop_callback&) = delete; stop_callback(stop_callback&&) = delete; stop_callback& operator=(stop_callback&&) = delete; private: struct _Cb_impl : stop_token::_Stop_cb { template<typename _Cb> explicit _Cb_impl(_Cb&& __cb) : _Stop_cb(&_S_execute), _M_cb(std::forward<_Cb>(__cb)) { } _Callback _M_cb; [[__gnu__::__nonnull__]] static void _S_execute(_Stop_cb* __that) noexcept { _Callback& __cb = static_cast<_Cb_impl*>(__that)->_M_cb; std::forward<_Callback>(__cb)(); } }; _Cb_impl _M_cb; stop_token::_Stop_state_ref _M_state; }; template<typename _Callback> stop_callback(stop_token, _Callback) -> stop_callback<_Callback>; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif // __cplusplus > 201703L #endif // _GLIBCXX_STOP_TOKEN
Save
cmd:
run