Working Draft, Standard for Programming Language C++ (N4713, 2017 year) - page 41

 

  Главная      Manuals     Working Draft, Standard for Programming Language C++ (N4713, 2017 year)

 

Search            copyright infringement  

 

 

 

 

 

 

 

 

 

 

 

Content      ..     39      40      41      42     ..

 

 

 

Working Draft, Standard for Programming Language C++ (N4713, 2017 year) - page 41

 

 

for which match[i].matched is true, match.position(i) shall return distance(begin, match[i].
first).
6
[ Note: This means that match.position(i) gives the offset from the beginning of the target sequence,
which is often not the same as the offset from the sequence passed in the call to regex_search.
— end
note ]
7
It is unspecified how the implementation makes these adjustments.
8
[ Note: This means that a compiler may call an implementation-specific search function, in which case
a user-defined specialization of regex_search will not be called.
— end note ]
regex_iterator operator++(int);
9
Effects: As if by:
regex_iterator tmp = *this;
++(*this);
return tmp;
31.12.2
Class template regex_token_iterator
[re.tokiter]
1
The class template regex_token_iterator is an iterator adaptor; that is to say it represents a new view of
an existing iterator sequence, by enumerating all the occurrences of a regular expression within that sequence,
and presenting one or more sub-expressions for each match found. Each position enumerated by the iterator
is a sub_match class template instance that represents what matched a particular sub-expression within the
regular expression.
2
When class regex_token_iterator is used to enumerate a single sub-expression with index -1 the iterator
performs field splitting: that is to say it enumerates one sub-expression for each section of the character
container sequence that does not match the regular expression specified.
3
After it is constructed, the iterator finds and stores a value regex_iterator<BidirectionalIterator>
position and sets the internal count N to zero. It also maintains a sequence subs which contains a list of
the sub-expressions which will be enumerated. Every time operator++ is used the count N is incremented; if
N exceeds or equals subs.size(), then the iterator increments member position and sets count N to zero.
4
If the end of sequence is reached (position is equal to the end of sequence iterator), the iterator becomes
equal to the end-of-sequence iterator value, unless the sub-expression being enumerated has index -1, in
which case the iterator enumerates one last sub-expression that contains all the characters from the end of
the last regular expression match to the end of the input sequence being enumerated, provided that this
would not be an empty sub-expression.
5
The default constructor constructs an end-of-sequence iterator object, which is the only legitimate iterator
to be used for the end condition. The result of operator* on an end-of-sequence iterator is not defined.
For any other iterator value a const sub_match<BidirectionalIterator>& is returned. The result of
operator-> on an end-of-sequence iterator is not defined. For any other iterator value a const sub_-
match<BidirectionalIterator>* is returned.
6
It is impossible to store things into regex_token_iterators. Two end-of-sequence iterators are always equal.
An end-of-sequence iterator is not equal to a non-end-of-sequence iterator. Two non-end-of-sequence iterators
are equal when they are constructed from the same arguments.
namespace std {
template<class BidirectionalIterator,
class charT = typename iterator_traits<BidirectionalIterator>::value_type,
class traits = regex_traits<charT>>
class regex_token_iterator {
public:
using regex_type
= basic_regex<charT, traits>;
using iterator_category = forward_iterator_tag;
using value_type
= sub_match<BidirectionalIterator>;
using difference_type
= ptrdiff_t;
using pointer
= const value_type*;
using reference
= const value_type&;
regex_token_iterator();
§ 31.12.2
1192
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
int submatch = 0,
regex_constants::match_flag_type m =
regex_constants::match_default);
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
const vector<int>& submatches,
regex_constants::match_flag_type m =
regex_constants::match_default);
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
initializer_list<int> submatches,
regex_constants::match_flag_type m =
regex_constants::match_default);
template<size_t N>
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
const int (&submatches)[N],
regex_constants::match_flag_type m =
regex_constants::match_default);
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator
b,
const regex_type&& re,
int submatch = 0,
regex_constants::match_flag_type m =
regex_constants::match_default) = delete;
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator
b,
const regex_type&& re,
const vector<int>& submatches,
regex_constants::match_flag_type m =
regex_constants::match_default) = delete;
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator
b,
const regex_type&& re,
initializer_list<int> submatches,
regex_constants::match_flag_type m =
regex_constants::match_default) = delete;
template<size_t N>
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator
b,
const regex_type&& re,
const int (&submatches)[N],
regex_constants::match_flag_type m =
regex_constants::match_default) = delete;
regex_token_iterator(const regex_token_iterator&);
regex_token_iterator& operator=(const regex_token_iterator&);
bool operator==(const regex_token_iterator&) const;
bool operator!=(const regex_token_iterator&) const;
const value_type& operator*() const;
const value_type* operator->() const;
regex_token_iterator& operator++();
regex_token_iterator operator++(int);
private:
using position_iterator =
regex_iterator<BidirectionalIterator, charT, traits>; // exposition only
position_iterator position;
// exposition only
const value_type* result;
// exposition only
value_type suffix;
// exposition only
size_t N;
// exposition only
vector<int> subs;
// exposition only
};
}
7
A suffix iterator is a regex_token_iterator object that points to a final sequence of characters at the end
of the target sequence. In a suffix iterator the member result holds a pointer to the data member suffix,
§ 31.12.2
1193
the value of the member suffix.match is true, suffix.first points to the beginning of the final sequence,
and suffix.second points to the end of the final sequence.
8
[ Note: For a suffix iterator, data member suffix.first is the same as the end of the last match found, and
suffix.second is the same as the end of the target sequence — end note ]
9
The current match is (*position).prefix() if subs[N] == -1, or (*position)[subs[N]] for any other
value of subs[N].
31.12.2.1
regex_token_iterator constructors
[re.tokiter.cnstr]
regex_token_iterator();
1
Effects: Constructs the end-of-sequence iterator.
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
int submatch = 0,
regex_constants::match_flag_type m = regex_constants::match_default);
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
const vector<int>& submatches,
regex_constants::match_flag_type m = regex_constants::match_default);
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
initializer_list<int> submatches,
regex_constants::match_flag_type m = regex_constants::match_default);
template<size_t N>
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b,
const regex_type& re,
const int (&submatches)[N],
regex_constants::match_flag_type m = regex_constants::match_default);
2
Requires: Each of the initialization values of submatches shall be >= -1.
3
Effects: The first constructor initializes the member subs to hold the single value submatch. The second
constructor initializes the member subs to hold a copy of the argument submatches. The third and
fourth constructors initialize the member subs to hold a copy of the sequence of integer values pointed to
by the iterator range [submatches.begin(), submatches.end()) and [&submatches, &submatches
+ N), respectively.
4
Each constructor then sets N to 0, and position to position_iterator(a, b, re, m). If position
is not an end-of-sequence iterator the constructor sets result to the address of the current match.
Otherwise if any of the values stored in subs is equal to -1 the constructor sets *this to a suffix iterator
that points to the range [a, b), otherwise the constructor sets *this to an end-of-sequence iterator.
31.12.2.2
regex_token_iterator comparisons
[re.tokiter.comp]
bool operator==(const regex_token_iterator& right) const;
1
Returns: true if *this and right are both end-of-sequence iterators, or if *this and right are
both suffix iterators and suffix == right.suffix; otherwise returns false if *this or right is an
end-of-sequence iterator or a suffix iterator. Otherwise returns true if position == right.position,
N == right.N, and subs == right.subs. Otherwise returns false.
bool operator!=(const regex_token_iterator& right) const;
2
Returns: !(*this == right).
31.12.2.3
regex_token_iterator indirection
[re.tokiter.deref]
const value_type& operator*() const;
1
Returns: *result.
§ 31.12.2.3
1194
const value_type* operator->() const;
2
Returns: result.
31.12.2.4
regex_token_iterator increment
[re.tokiter.incr]
regex_token_iterator& operator++();
1
Effects: Constructs a local variable prev of type position_iterator, initialized with the value of
position.
2
If *this is a suffix iterator, sets *this to an end-of-sequence iterator.
3
Otherwise, if N + 1 < subs.size(), increments N and sets result to the address of the current match.
4
Otherwise, sets N to 0 and increments position. If position is not an end-of-sequence iterator the
operator sets result to the address of the current match.
5
Otherwise, if any of the values stored in subs is equal to -1 and prev->suffix().length() is not
0 the operator sets *this to a suffix iterator that points to the range [prev->suffix().first,
prev->suffix().second).
6
Otherwise, sets *this to an end-of-sequence iterator.
7
Returns: *this
regex_token_iterator& operator++(int);
8
Effects: Constructs a copy tmp of *this, then calls ++(*this).
9
Returns: tmp.
31.13
Modified ECMAScript regular expression grammar
[re.grammar]
1
The regular expression grammar recognized by basic_regex objects constructed with the ECMAScript flag
is that specified by ECMA-262, except as specified below.
2
Objects of type specialization of basic_regex store within themselves a default-constructed instance of
their traits template parameter, henceforth referred to as traits_inst. This traits_inst object is
used to support localization of the regular expression; basic_regex member functions shall not call any
locale dependent C or C++ API, including the formatted string input functions. Instead they shall call the
appropriate traits member function to achieve the required effect.
3
The following productions within the ECMAScript grammar are modified as follows:
ClassAtom ::
-
ClassAtomNoDash
ClassAtomExClass
ClassAtomCollatingElement
ClassAtomEquivalence
IdentityEscape ::
SourceCharacter but not c
4
The following new productions are then added:
ClassAtomExClass ::
[: ClassName :]
ClassAtomCollatingElement ::
[. ClassName .]
ClassAtomEquivalence ::
[= ClassName =]
ClassName ::
ClassNameCharacter
ClassNameCharacter ClassName
ClassNameCharacter ::
SourceCharacter but not one of "." "=" ":"
§ 31.13
1195
5
The productions ClassAtomExClass, ClassAtomCollatingElement and ClassAtomEquivalence provide
functionality equivalent to that of the same features in regular expressions in POSIX.
6
The regular expression grammar may be modified by any regex_constants::syntax_option_type flags
specified when constructing an object of type specialization of basic_regex according to the rules in Table
130.
7
A ClassName production, when used in ClassAtomExClass, is not valid if traits_inst.lookup_classname
returns zero for that name. The names recognized as valid ClassNames are determined by the type of the
traits class, but at least the following names shall be recognized: alnum, alpha, blank, cntrl, digit, graph,
lower, print, punct, space, upper, xdigit, d, s, w. In addition the following expressions shall be equivalent:
\d and [[:digit:]]
\D and [^[:digit:]]
\s and [[:space:]]
\S and [^[:space:]]
\w and [_[:alnum:]]
\W and [^_[:alnum:]]
8
A ClassName production when used in a ClassAtomCollatingElement production is not valid if the value
returned by traits_inst.lookup_collatename for that name is an empty string.
9
The results from multiple calls to traits_inst.lookup_classname can be bitwise OR’ed together and
subsequently passed to traits_inst.isctype.
10
A ClassName production when used in a ClassAtomEquivalence production is not valid if the value returned
by traits_inst.lookup_collatename for that name is an empty string or if the value returned by traits_-
inst.transform_primary for the result of the call to traits_inst.lookup_collatename is an empty
string.
11
When the sequence of characters being transformed to a finite state machine contains an invalid class name
the translator shall throw an exception object of type regex_error.
12
If the CV of a UnicodeEscapeSequence is greater than the largest value that can be held in an object of type
charT the translator shall throw an exception object of type regex_error. [ Note: This means that values of
the form "uxxxx" that do not fit in a character are invalid.
— end note ]
13
Where the regular expression grammar requires the conversion of a sequence of characters to an integral
value, this is accomplished by calling traits_inst.value.
14
The behavior of the internal finite state machine representation when used to match a sequence of characters
is as described in ECMA-262. The behavior is modified according to any match_flag_type flags (31.5.2)
specified when using the regular expression object in one of the regular expression algorithms (31.11). The
behavior is also localized by interaction with the traits class template parameter as follows:
(14.1)
During matching of a regular expression finite state machine against a sequence of characters, two
characters c and d are compared using the following rules:
(14.1.1)
if
(flags() & regex_constants::icase) the two characters are equal if traits_inst.trans-
late_nocase(c) == traits_inst.translate_nocase(d);
(14.1.2)
otherwise, if flags() & regex_constants::collate the two characters are equal if traits_-
inst.translate(c) == traits_inst.translate(d);
(14.1.3)
otherwise, the two characters are equal if c == d.
(14.2)
During matching of a regular expression finite state machine against a sequence of characters, comparison
of a collating element range c1-c2 against a character c is conducted as follows: if flags() & regex_-
constants::collate is false then the character c is matched if c1 <= c && c <= c2, otherwise c is
matched in accordance with the following algorithm:
string_type str1 = string_type(1,
flags() & icase ?
traits_inst.translate_nocase(c1) : traits_inst.translate(c1);
§ 31.13
1196
string_type str2 = string_type(1,
flags() & icase ?
traits_inst.translate_nocase(c2) : traits_inst.translate(c2);
string_type str = string_type(1,
flags() & icase ?
traits_inst.translate_nocase(c) : traits_inst.translate(c);
return traits_inst.transform(str1.begin(), str1.end())
<= traits_inst.transform(str.begin(), str.end())
&& traits_inst.transform(str.begin(), str.end())
<= traits_inst.transform(str2.begin(), str2.end());
(14.3)
During matching of a regular expression finite state machine against a sequence of characters, testing
whether a collating element is a member of a primary equivalence class is conducted by first converting
the collating element and the equivalence class to sort keys using traits::transform_primary, and
then comparing the sort keys for equality.
(14.4)
During matching of a regular expression finite state machine against a sequence of characters, a
character c is a member of a character class designated by an iterator range [first, last) if traits_-
inst.isctype(c, traits_inst.lookup_classname(first, last, flags() & icase)) is true.
§ 31.13
1197
32
Atomic operations library
[atomics]
32.1
General
[atomics.general]
1
This Clause describes components for fine-grained atomic access. This access is provided via operations on
atomic objects.
2
The following subclauses describe atomics requirements and components for types and operations, as
summarized below.
Table 137 — Atomics library summary
Subclause
Header(s)
32.4
Order and Consistency
32.5
Lock-free Property
32.6
Atomic Types
<atomic>
32.6.1
Operations on Atomic Types
32.8
Flag Type and Operations
32.9
Fences
32.2
Header <atomic> synopsis
[atomics.syn]
namespace std {
// 32.4, order and consistency
enum class memory_order : unspecified ;
template<class T>
T kill_dependency(T y) noexcept;
// 32.5, lock-free property
#define ATOMIC_BOOL_LOCK_FREE unspecified
#define ATOMIC_CHAR_LOCK_FREE unspecified
#define ATOMIC_CHAR16_T_LOCK_FREE unspecified
#define ATOMIC_CHAR32_T_LOCK_FREE unspecified
#define ATOMIC_WCHAR_T_LOCK_FREE unspecified
#define ATOMIC_SHORT_LOCK_FREE unspecified
#define ATOMIC_INT_LOCK_FREE unspecified
#define ATOMIC_LONG_LOCK_FREE unspecified
#define ATOMIC_LLONG_LOCK_FREE unspecified
#define ATOMIC_POINTER_LOCK_FREE unspecified
// 32.6, atomic
template<class T> struct atomic;
// 32.6.4, partial specialization for pointers
template<class T> struct atomic<T*>;
// 32.7, non-member functions
template<class T>
bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
template<class T>
bool atomic_is_lock_free(const atomic<T>*) noexcept;
template<class T>
void atomic_init(volatile atomic<T>*, typename atomic<T>::value_type)
noexcept;
template<class T>
void atomic_init(atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
void atomic_store(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
void atomic_store(atomic<T>*, typename atomic<T>::value_type) noexcept;
§ 32.2
1198
template<class T>
void atomic_store_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
void atomic_store_explicit(atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_load(const volatile atomic<T>*) noexcept;
template<class T>
T atomic_load(const atomic<T>*) noexcept;
template<class T>
T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
template<class T>
T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
template<class T>
T atomic_exchange(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_exchange(atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_exchange_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_exchange_explicit(atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_weak(volatile atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_weak(atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_strong(volatile atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_strong(atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_weak_explicit(atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_strong_explicit(atomic<T>*,
typename atomic<T>::value_type*,
typename atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
T atomic_fetch_add(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
§
32.2
1199
template<class T>
T atomic_fetch_add(atomic<T>*, typename atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_add_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_add_explicit(atomic<T>*, typename atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_sub(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_sub_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_sub_explicit(atomic<T>*, typename atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_and(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_and(atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_and_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_and_explicit(atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_or(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_or(atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_or_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_or_explicit(atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_xor(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_xor(atomic<T>*, typename atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_xor_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_xor_explicit(atomic<T>*, typename atomic<T>::value_type,
memory_order) noexcept;
// 32.6.1, initialization
#define ATOMIC_VAR_INIT(value) see below
// 32.3, type aliases
using atomic_bool
= atomic<bool>;
using atomic_char
= atomic<char>;
using atomic_schar
= atomic<signed char>;
using atomic_uchar
= atomic<unsigned char>;
using atomic_short
= atomic<short>;
using atomic_ushort
= atomic<unsigned short>;
using atomic_int
= atomic<int>;
using atomic_uint
= atomic<unsigned int>;
using atomic_long
= atomic<long>;
using atomic_ulong
= atomic<unsigned long>;
using atomic_llong
= atomic<long long>;
§
32.2
1200
using
atomic_ullong
=
atomic<unsigned long long>;
using
atomic_char16_t
=
atomic<char16_t>;
using
atomic_char32_t
=
atomic<char32_t>;
using
atomic_wchar_t
=
atomic<wchar_t>;
using
atomic_int8_t
=
atomic<int8_t>;
using
atomic_uint8_t
=
atomic<uint8_t>;
using
atomic_int16_t
=
atomic<int16_t>;
using
atomic_uint16_t
=
atomic<uint16_t>;
using
atomic_int32_t
=
atomic<int32_t>;
using
atomic_uint32_t
=
atomic<uint32_t>;
using
atomic_int64_t
=
atomic<int64_t>;
using
atomic_uint64_t
=
atomic<uint64_t>;
using
atomic_int_least8_t
=
atomic<int_least8_t>;
using
atomic_uint_least8_t
=
atomic<uint_least8_t>;
using
atomic_int_least16_t
=
atomic<int_least16_t>;
using
atomic_uint_least16_t
=
atomic<uint_least16_t>;
using
atomic_int_least32_t
=
atomic<int_least32_t>;
using
atomic_uint_least32_t
=
atomic<uint_least32_t>;
using
atomic_int_least64_t
=
atomic<int_least64_t>;
using
atomic_uint_least64_t
=
atomic<uint_least64_t>;
using
atomic_int_fast8_t
=
atomic<int_fast8_t>;
using
atomic_uint_fast8_t
=
atomic<uint_fast8_t>;
using
atomic_int_fast16_t
=
atomic<int_fast16_t>;
using
atomic_uint_fast16_t
=
atomic<uint_fast16_t>;
using
atomic_int_fast32_t
=
atomic<int_fast32_t>;
using
atomic_uint_fast32_t
=
atomic<uint_fast32_t>;
using
atomic_int_fast64_t
=
atomic<int_fast64_t>;
using
atomic_uint_fast64_t
=
atomic<uint_fast64_t>;
using
atomic_intptr_t
=
atomic<intptr_t>;
using
atomic_uintptr_t
=
atomic<uintptr_t>;
using
atomic_size_t
=
atomic<size_t>;
using
atomic_ptrdiff_t
=
atomic<ptrdiff_t>;
using
atomic_intmax_t
=
atomic<intmax_t>;
using
atomic_uintmax_t
=
atomic<uintmax_t>;
// 32.8, flag type and operations
struct atomic_flag;
bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;
bool atomic_flag_test_and_set(atomic_flag*) noexcept;
bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order)
noexcept;
bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept;
void atomic_flag_clear(volatile atomic_flag*) noexcept;
void atomic_flag_clear(atomic_flag*) noexcept;
void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept;
void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept;
#define ATOMIC_FLAG_INIT see below
// 32.9, fences
extern "C" void atomic_thread_fence(memory_order) noexcept;
extern "C" void atomic_signal_fence(memory_order) noexcept;
}
32.3
Type aliases
[atomics.alias]
1
The type aliases atomic_intN _t, atomic_uintN _t, atomic_intptr_t, and atomic_uintptr_t are defined
if and only if intN _t, uintN _t, intptr_t, and uintptr_t are defined, respectively.
32.4
Order and consistency
[atomics.order]
namespace std {
enum class memory_order : unspecified
{
§ 32.4
1201
relaxed, consume, acquire, release, acq_rel, seq_cst
};
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
}
1
The enumeration memory_order specifies the detailed regular (non-atomic) memory synchronization order as
defined in 6.8.2 and may provide for operation ordering. Its enumerated values and their meanings are as
follows:
(1.1)
memory_order::relaxed: no operation orders memory.
(1.2)
memory_order::release, memory_order::acq_rel, and memory_order::seq_cst: a store operation
performs a release operation on the affected memory location.
(1.3)
memory_order::consume: a load operation performs a consume operation on the affected memory
location. [Note: Prefer memory_order::acquire, which provides stronger guarantees than memory_-
order::consume. Implementations have found it infeasible to provide performance better than that of
memory_order::acquire. Specification revisions are under consideration.
— end note ]
(1.4)
memory_order::acquire, memory_order::acq_rel, and memory_order::seq_cst: a load operation
performs an acquire operation on the affected memory location.
[ Note: Atomic operations specifying memory_order::relaxed are relaxed with respect to memory ordering.
Implementations must still guarantee that any given atomic access to a particular atomic object be indivisible
with respect to all other atomic accesses to that object.
— end note ]
2
An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic
operation B that performs an acquire operation on M and takes its value from any side effect in the release
sequence headed by A.
3
There shall be a single total order S on all memory_order::seq_cst operations, consistent with the “happens
before” order and modification orders for all affected locations, such that each memory_order::seq_cst
operation B that loads a value from an atomic object M observes one of the following values:
(3.1)
the result of the last modification A of M that precedes B in S, if it exists, or
(3.2)
if A exists, the result of some modification of M that is not memory_order::seq_cst and that does
not happen before A, or
(3.3)
if A does not exist, the result of some modification of M that is not memory_order::seq_cst.
[Note: Although it is not explicitly required that S include locks, it can always be extended to an order
that does include lock and unlock operations, since the ordering between those is already included in the
“happens before” ordering.
— end note ]
4
For an atomic operation B that reads the value of an atomic object M, if there is a memory_order::seq_cst
fence X sequenced before B, then B observes either the last memory_order::seq_cst modification of M
preceding X in the total order S or a later modification of M in its modification order.
5
For atomic operations A and B on an atomic object M, where A modifies M and B takes its value, if there is
a memory_order::seq_cst fence X such that A is sequenced before X and B follows X in S, then B observes
either the effects of A or a later modification of M in its modification order.
6
For atomic operations A and B on an atomic object M, where A modifies M and B takes its value, if there
are memory_order::seq_cst fences X and Y such that A is sequenced before X, Y is sequenced before B,
and X precedes Y in S, then B observes either the effects of A or a later modification of M in its modification
order.
7
For atomic modifications A and B of an atomic object M, B occurs later than A in the modification order of
M if:
(7.1)
there is a memory_order::seq_cst fence X such that A is sequenced before X, and X precedes B in S,
or
(7.2)
there is a memory_order::seq_cst fence Y such that Y is sequenced before B, and A precedes Y in
S, or
§ 32.4
1202
(7.3)
there are memory_order::seq_cst fences X and Y such that A is sequenced before X, Y is sequenced
before B, and X precedes Y in S.
8
[ Note: memory_order::seq_cst ensures sequential consistency only for a program that is free of data races
and uses exclusively memory_order::seq_cst operations. Any use of weaker ordering will invalidate this
guarantee unless extreme care is used. In particular, memory_order::seq_cst fences ensure a total order
only for the fences themselves. Fences cannot, in general, be used to restore sequential consistency for atomic
operations with weaker ordering specifications.
— end note ]
9
Implementations should ensure that no “out-of-thin-air” values are computed that circularly depend on their
own computation.
[ Note: For example, with x and y initially zero,
// Thread 1:
r1 = y.load(memory_order::relaxed);
x.store(r1, memory_order::relaxed);
// Thread 2:
r2 = x.load(memory_order::relaxed);
y.store(r2, memory_order::relaxed);
should not produce r1 == r2 == 42, since the store of 42 to y is only possible if the store to x stores 42,
which circularly depends on the store to y storing 42. Note that without this restriction, such an execution is
possible.
— end note ]
10
[Note: The recommendation similarly disallows r1 == r2 == 42 in the following example, with x and y
again initially zero:
// Thread 1:
r1 = x.load(memory_order::relaxed);
if (r1 == 42) y.store(42, memory_order::relaxed);
// Thread 2:
r2 = y.load(memory_order::relaxed);
if (r2 == 42) x.store(42, memory_order::relaxed);
— end note ]
11
Atomic read-modify-write operations shall always read the last value (in the modification order) written
before the write associated with the read-modify-write operation.
12
Implementations should make atomic stores visible to atomic loads within a reasonable amount of time.
template<class T>
T kill_dependency(T y) noexcept;
13
Effects: The argument does not carry a dependency to the return value (6.8.2).
14
Returns: y.
32.5
Lock-free property
[atomics.lockfree]
#define ATOMIC_BOOL_LOCK_FREE unspecified
#define ATOMIC_CHAR_LOCK_FREE unspecified
#define ATOMIC_CHAR16_T_LOCK_FREE unspecified
#define ATOMIC_CHAR32_T_LOCK_FREE unspecified
#define ATOMIC_WCHAR_T_LOCK_FREE unspecified
#define ATOMIC_SHORT_LOCK_FREE unspecified
#define ATOMIC_INT_LOCK_FREE unspecified
#define ATOMIC_LONG_LOCK_FREE unspecified
#define ATOMIC_LLONG_LOCK_FREE unspecified
#define ATOMIC_POINTER_LOCK_FREE unspecified
1
The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the corresponding atomic types, with
the signed and unsigned variants grouped together. The properties also apply to the corresponding (partial)
specializations of the atomic template. A value of 0 indicates that the types are never lock-free. A value of 1
indicates that the types are sometimes lock-free. A value of 2 indicates that the types are always lock-free.
2
The function atomic_is_lock_free (32.6.1) indicates whether the object is lock-free. In any given program
execution, the result of the lock-free query shall be consistent for all pointers of the same type.
3
Atomic operations that are not lock-free are considered to potentially block (6.8.2.2).
§ 32.5
1203
4
[Note: Operations that are lock-free should also be address-free. That is, atomic operations on the same
memory location via two different addresses will communicate atomically. The implementation should not
depend on any per-process state. This restriction enables communication by memory that is mapped into a
process more than once and by memory that is shared between two processes.
— end note ]
32.6
Class template atomic
[atomics.types.generic]
namespace std {
template<class T> struct atomic {
using value_type = T;
static constexpr bool is_always_lock_free = implementation-defined ;
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;
void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
void store(T, memory_order = memory_order::seq_cst) noexcept;
T load(memory_order = memory_order::seq_cst) const volatile noexcept;
T load(memory_order = memory_order::seq_cst) const noexcept;
operator T() const volatile noexcept;
operator T() const noexcept;
T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
T exchange(T, memory_order = memory_order::seq_cst) noexcept;
bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
atomic() noexcept = default;
constexpr atomic(T) noexcept;
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
atomic& operator=(const atomic&) volatile = delete;
T operator=(T) volatile noexcept;
T operator=(T) noexcept;
};
}
1
The template argument for T shall be trivially copyable (6.7). [ Note: Type arguments that are not also
statically initializable may be difficult to use.
— end note ]
2
The specialization atomic<bool> is a standard-layout struct.
3
[Note: The representation of an atomic specialization need not have the same size as its corresponding
argument type. Specializations should have the same size whenever possible, as this reduces the effort required
to port existing code.
— end note ]
32.6.1
Operations on atomic types
[atomics.types.operations]
1
[ Note: Many operations are volatile-qualified. The “volatile as device register” semantics have not changed in
the standard. This qualification means that volatility is preserved when applying these operations to volatile
objects. It does not mean that operations on non-volatile objects become volatile.
— end note ]
atomic() noexcept = default;
2
Effects: Leaves the atomic object in an uninitialized state. [ Note: These semantics ensure compatibility
with C. — end note ]
constexpr atomic(T desired) noexcept;
3
Effects: Initializes the object with the value desired. Initialization is not an atomic operation
(6.8.2).
[Note: It is possible to have an access to an atomic object A race with its construction, for
example by communicating the address of the just-constructed object A to another thread via memory_-
order::relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in
the receiving thread. This results in undefined behavior.
— end note ]
§ 32.6.1
1204
#define ATOMIC_VAR_INIT(value) see below
4
The macro expands to a token sequence suitable for constant initialization of an atomic variable of
static storage duration of a type that is initialization-compatible with value. [Note: This operation
may need to initialize locks.
— end note ] Concurrent access to the variable being initialized, even via
an atomic operation, constitutes a data race. [ Example:
atomic<int> v = ATOMIC_VAR_INIT(5);
— end example ]
static constexpr bool is_always_lock_free = implementation-defined ;
5
The static data member is_always_lock_free is true if the atomic type’s operations are always
lock-free, and false otherwise. [ Note: The value of is_always_lock_free is consistent with the value
of the corresponding ATOMIC_..._LOCK_FREE macro, if defined.
— end note ]
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;
6
Returns: true if the object’s operations are lock-free, false otherwise. [ Note: The return value of the
is_lock_free member function is consistent with the value of is_always_lock_free for the same
type.
— end note ]
void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
7
Requires: The order argument shall not be memory_order::consume, memory_order::acquire, nor
memory_order::acq_rel.
8
Effects: Atomically replaces the value pointed to by this with the value of desired. Memory is
affected according to the value of order.
T operator=(T desired) volatile noexcept;
T operator=(T desired) noexcept;
9
Effects: Equivalent to store(desired).
10
Returns: desired.
T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
T load(memory_order order = memory_order::seq_cst) const noexcept;
11
Requires: The order argument shall not be memory_order::release nor memory_order::acq_rel.
12
Effects: Memory is affected according to the value of order.
13
Returns: Atomically returns the value pointed to by this.
operator T() const volatile noexcept;
operator T() const noexcept;
14
Effects: Equivalent to: return load();
T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
15
Effects: Atomically replaces the value pointed to by this with desired. Memory is affected according
to the value of order. These operations are atomic read-modify-write operations (6.8.2).
16
Returns: Atomically returns the value pointed to by this immediately before the effects.
bool compare_exchange_weak(T& expected, T desired,
memory_order success, memory_order failure) volatile noexcept;
bool compare_exchange_weak(T& expected, T desired,
memory_order success, memory_order failure) noexcept;
bool compare_exchange_strong(T& expected, T desired,
memory_order success, memory_order failure) volatile noexcept;
bool compare_exchange_strong(T& expected, T desired,
memory_order success, memory_order failure) noexcept;
bool compare_exchange_weak(T& expected, T desired,
memory_order order = memory_order::seq_cst) volatile noexcept;
§ 32.6.1
1205
bool
compare_exchange_weak(T& expected, T desired,
memory_order order = memory_order::seq_cst) noexcept;
bool
compare_exchange_strong(T& expected, T desired,
memory_order order = memory_order::seq_cst) volatile noexcept;
bool
compare_exchange_strong(T& expected, T desired,
memory_order order = memory_order::seq_cst) noexcept;
17
Requires: The failure argument shall not be memory_order::release nor memory_order::acq_rel.
18
Effects: Retrieves the value in expected. It then atomically compares the contents of the memory
pointed to by this for equality with that previously retrieved from expected, and if true, replaces the
contents of the memory pointed to by this with that in desired. If and only if the comparison is true,
memory is affected according to the value of success, and if the comparison is false, memory is affected
according to the value of failure. When only one memory_order argument is supplied, the value of
success is order, and the value of failure is order except that a value of memory_order::acq_-
rel shall be replaced by the value memory_order::acquire and a value of memory_order::release
shall be replaced by the value memory_order::relaxed. If and only if the comparison is false then,
after the atomic operation, the contents of the memory in expected are replaced by the value read
from the memory pointed to by this during the atomic comparison. If the operation returns true,
these operations are atomic read-modify-write operations (6.8.2) on the memory pointed to by this.
Otherwise, these operations are atomic load operations on that memory.
19
Returns: The result of the comparison.
20
[ Note: For example, the effect of compare_exchange_strong is
if (memcmp(this, &expected, sizeof(*this)) == 0)
memcpy(this, &desired, sizeof(*this));
else
memcpy(expected, this, sizeof(*this));
— end note ]
[Example: The expected use of the compare-and-exchange operations is as follows.
The compare-and-exchange operations will update expected when another iteration of the loop is
needed.
expected = current.load();
do {
desired = function(expected);
} while (!current.compare_exchange_weak(expected, desired));
— end example ] [ Example: Because the expected value is updated only on failure, code releasing the
memory containing the expected value on success will work. E.g. list head insertion will act atomically
and would not introduce a data race in the following code:
do {
p->next = head; // make new list node point to the current head
} while (!head.compare_exchange_weak(p->next, p)); // try to insert
— end example ]
21
Implementations should ensure that weak compare-and-exchange operations do not consistently return
false unless either the atomic object has value different from expected or there are concurrent
modifications to the atomic object.
22
Remarks: A weak compare-and-exchange operation may fail spuriously. That is, even when the
contents of memory referred to by expected and this are equal, it may return false and store
back to expected the same memory contents that were originally there. [Note: This spurious failure
enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked
store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare-
and-exchange will be in a loop. When a compare-and-exchange is in a loop, the weak version will yield
better performance on some platforms. When a weak compare-and-exchange would require a loop and
a strong one would not, the strong one is preferable.
— end note ]
23
[ Note: The memcpy and memcmp semantics of the compare-and-exchange operations may result in failed
comparisons for values that compare equal with operator== if the underlying type has padding bits,
trap bits, or alternate representations of the same value. — end note ]
§ 32.6.1
1206
32.6.2
Specializations for integers
[atomics.types.int]
1
There are specializations of the atomic template for the integral types char, signed char, unsigned
char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long
long, char16_t, char32_t, wchar_t, and any other types needed by the typedefs in the header <cstdint>.
For each such integral type integral , the specialization atomic<integral > provides additional atomic
operations appropriate to integral types. [ Note: For the specialization atomic<bool>, see 32.6.
— end note ]
namespace std {
template<> struct atomic<integral > {
using value_type = integral ;
using difference_type = value_type;
static constexpr bool is_always_lock_free = implementation-defined ;
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;
void store(integral, memory_order = memory_order::seq_cst) volatile noexcept;
void store(integral, memory_order = memory_order::seq_cst) noexcept;
integral load(memory_order = memory_order::seq_cst) const volatile noexcept;
integral load(memory_order = memory_order::seq_cst) const noexcept;
operator integral() const volatile noexcept;
operator integral() const noexcept;
integral exchange(integral, memory_order = memory_order::seq_cst) volatile noexcept;
integral exchange(integral, memory_order = memory_order::seq_cst) noexcept;
bool compare_exchange_weak(integral &, integral,
memory_order, memory_order) volatile noexcept;
bool compare_exchange_weak(integral &, integral,
memory_order, memory_order) noexcept;
bool compare_exchange_strong(integral &, integral,
memory_order, memory_order) volatile noexcept;
bool compare_exchange_strong(integral &, integral,
memory_order, memory_order) noexcept;
bool compare_exchange_weak(integral &, integral,
memory_order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_weak(integral &, integral,
memory_order = memory_order::seq_cst) noexcept;
bool compare_exchange_strong(integral &, integral,
memory_order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_strong(integral &, integral,
memory_order = memory_order::seq_cst) noexcept;
integral fetch_add(integral, memory_order = memory_order::seq_cst) volatile noexcept;
integral fetch_add(integral, memory_order = memory_order::seq_cst) noexcept;
integral fetch_sub(integral, memory_order = memory_order::seq_cst) volatile noexcept;
integral fetch_sub(integral, memory_order = memory_order::seq_cst) noexcept;
integral fetch_and(integral, memory_order = memory_order::seq_cst) volatile noexcept;
integral fetch_and(integral, memory_order = memory_order::seq_cst) noexcept;
integral fetch_or(integral, memory_order = memory_order::seq_cst) volatile noexcept;
integral fetch_or(integral, memory_order = memory_order::seq_cst) noexcept;
integral fetch_xor(integral, memory_order = memory_order::seq_cst) volatile noexcept;
integral fetch_xor(integral, memory_order = memory_order::seq_cst) noexcept;
atomic() noexcept = default;
constexpr atomic(integral) noexcept;
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
atomic& operator=(const atomic&) volatile = delete;
integral operator=(integral) volatile noexcept;
integral operator=(integral) noexcept;
integral operator++(int) volatile noexcept;
integral operator++(int) noexcept;
integral operator--(int) volatile noexcept;
integral operator--(int) noexcept;
integral operator++() volatile noexcept;
integral operator++() noexcept;
integral operator--() volatile noexcept;
§
32.6.2
1207
integral operator--() noexcept;
integral operator+=(integral) volatile noexcept;
integral operator+=(integral) noexcept;
integral operator-=(integral) volatile noexcept;
integral operator-=(integral) noexcept;
integral operator&=(integral) volatile noexcept;
integral operator&=(integral) noexcept;
integral operator|=(integral) volatile noexcept;
integral operator|=(integral) noexcept;
integral operator^=(integral) volatile noexcept;
integral operator^=(integral) noexcept;
};
}
2
The atomic integral specializations are standard-layout structs. They each have a trivial default constructor
and a trivial destructor.
3
Descriptions are provided below only for members that differ from the primary template.
4
The following operations perform arithmetic computations. The key, operator, and computation correspon-
dence is:
Table 138 — Atomic arithmetic computations
key Op Computation
key Op Computation
add
+
addition
sub
-
subtraction
or
|
bitwise inclusive or
xor
^
bitwise exclusive or
and
&
bitwise and
T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
5
Effects: Atomically replaces the value pointed to by this with the result of the computation applied
to the value pointed to by this and the given operand. Memory is affected according to the value of
order. These operations are atomic read-modify-write operations (6.8.2).
6
Returns: Atomically, the value pointed to by this immediately before the effects.
7
Remarks: For signed integer types, arithmetic is defined to use two’s complement representation. There
are no undefined results.
T operator op =(T operand) volatile noexcept;
T operator op =(T operand) noexcept;
8
Effects: Equivalent to: return fetch_key (operand) op operand;
32.6.3
Specializations for floating-point types
[atomics.types.float]
1
There are specializations of the atomic template for the floating-point types float, double, and long
double. For each such floating-point type floating-point, the specialization atomic<floating-point >
provides additional atomic operations appropriate to floating-point types.
namespace std {
template<> struct atomic<floating-point > {
static constexpr bool is_always_lock_free = implementation-defined ;
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;
void store(floating-point, memory_order = memory_order_seq_cst) volatile noexcept;
void store(floating-point, memory_order = memory_order_seq_cst) noexcept;
floating-point load(memory_order = memory_order_seq_cst) volatile noexcept;
floating-point load(memory_order = memory_order_seq_cst) noexcept;
operator floating-point() volatile noexcept;
operator floating-point() noexcept;
floating-point exchange(floating-point,
memory_order = memory_order_seq_cst) volatile noexcept;
floating-point exchange(floating-point,
memory_order = memory_order_seq_cst) noexcept;
§ 32.6.3
1208
bool compare_exchange_weak(floating-point &, floating-point,
memory_order, memory_order) volatile noexcept;
bool compare_exchange_weak(floating-point &, floating-point,
memory_order, memory_order) noexcept;
bool compare_exchange_strong(floating-point &, floating-point,
memory_order, memory_order) volatile noexcept;
bool compare_exchange_strong(floating-point &, floating-point,
memory_order, memory_order) noexcept;
bool compare_exchange_weak(floating-point &, floating-point,
memory_order = memory_order_seq_cst) volatile noexcept;
bool compare_exchange_weak(floating-point &, floating-point,
memory_order = memory_order_seq_cst) noexcept;
bool compare_exchange_strong(floating-point &, floating-point,
memory_order = memory_order_seq_cst) volatile noexcept;
bool compare_exchange_strong(floating-point &, floating-point,
memory_order = memory_order_seq_cst) noexcept;
floating-point fetch_add(floating-point,
memory_order = memory_order_seq_cst) volatile noexcept;
floating-point fetch_add(floating-point,
memory_order = memory_order_seq_cst) noexcept;
floating-point fetch_sub(floating-point,
memory_order = memory_order_seq_cst) volatile noexcept;
floating-point fetch_sub(floating-point,
memory_order = memory_order_seq_cst) noexcept;
atomic() noexcept = default;
constexpr atomic(floating-point ) noexcept;
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
atomic& operator=(const atomic&) volatile = delete;
floating-point operator=(floating-point ) volatile noexcept;
floating-point operator=(floating-point ) noexcept;
floating-point operator+=(floating-point ) volatile noexcept;
floating-point operator+=(floating-point ) noexcept;
floating-point operator-=(floating-point ) volatile noexcept;
floating-point operator-=(floating-point ) noexcept;
};
}
2
The atomic floating-point specializations are standard-layout structs. They each have a trivial default
constructor and a trivial destructor.
3
Descriptions are provided below only for members that differ from the primary template.
4
The following operations perform arithmetic addition and subtraction computations. The key, operator, and
computation correspondence are identified in Table 138.
T A::fetch_key(T operand, memory_order order = memory_order_seq_cst) volatile noexcept;
T A::fetch_key(T operand, memory_order order = memory_order_seq_cst) noexcept;
5
Effects: Atomically replaces the value pointed to by this with the result of the computation applied
to the value pointed to by this and the given operand. Memory is affected according to the value of
order. These operations are atomic read-modify-write operations (6.8.2).
6
Returns: Atomically, the value pointed to by this immediately before the effects.
7
Remarks: If the result is not a representable value for its type (8.1) the result is unspecified, but the
operations otherwise have no undefined behavior. Atomic arithmetic operations on floating-point
should conform to the std::numeric_limits<floating-point > traits associated with the floating-
point type (21.3.2). The floating-point environment (29.4) for atomic arithmetic operations on
floating-point may be different than the calling thread’s floating-point environment.
T operator op =(T operand) volatile noexcept;
§ 32.6.3
1209
T operator op =(T operand) noexcept;
8
Effects: Equivalent to: return fetch_key (operand) op operand;
9
Remarks: If the result is not a representable value for its type (8.1) the result is unspecified, but the
operations otherwise have no undefined behavior. Atomic arithmetic operations on floating-point
should conform to the std::numeric_limits<floating-point > traits associated with the floating-
point type (21.3.2). The floating-point environment (29.4) for atomic arithmetic operations on
floating-point may be different than the calling thread’s floating-point environment.
32.6.4
Partial specialization for pointers
[atomics.types.pointer]
namespace std {
template<class T> struct atomic<T*> {
using value_type = T*;
using difference_type = ptrdiff_t;
static constexpr bool is_always_lock_free = implementation-defined ;
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;
void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
void store(T*, memory_order = memory_order::seq_cst) noexcept;
T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
T* load(memory_order = memory_order::seq_cst) const noexcept;
operator T*() const volatile noexcept;
operator T*() const noexcept;
T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
bool compare_exchange_weak(T*&, T*,
memory_order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_weak(T*&, T*,
memory_order = memory_order::seq_cst) noexcept;
bool compare_exchange_strong(T*&, T*,
memory_order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_strong(T*&, T*,
memory_order = memory_order::seq_cst) noexcept;
T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
atomic() noexcept = default;
constexpr atomic(T*) noexcept;
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
atomic& operator=(const atomic&) volatile = delete;
T* operator=(T*) volatile noexcept;
T* operator=(T*) noexcept;
T* operator++(int) volatile noexcept;
T* operator++(int) noexcept;
T* operator--(int) volatile noexcept;
T* operator--(int) noexcept;
T* operator++() volatile noexcept;
T* operator++() noexcept;
T* operator--() volatile noexcept;
T* operator--() noexcept;
T* operator+=(ptrdiff_t) volatile noexcept;
T* operator+=(ptrdiff_t) noexcept;
T* operator-=(ptrdiff_t) volatile noexcept;
T* operator-=(ptrdiff_t) noexcept;
§ 32.6.4
1210
};
}
1
There is a partial specialization of the atomic class template for pointers. Specializations of this partial
specialization are standard-layout structs. They each have a trivial default constructor and a trivial destructor.
2
Descriptions are provided below only for members that differ from the primary template.
3
The following operations perform pointer arithmetic. The key, operator, and computation correspondence is:
Table 139 — Atomic pointer computations
Key Op Computation
Key Op Computation
add
+
addition
sub
-
subtraction
T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;
T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept;
4
Requires: T shall be an object type, otherwise the program is ill-formed. [ Note: Pointer arithmetic on
void* or function pointers is ill-formed.
— end note ]
5
Effects: Atomically replaces the value pointed to by this with the result of the computation applied
to the value pointed to by this and the given operand. Memory is affected according to the value of
order. These operations are atomic read-modify-write operations (6.8.2).
6
Returns: Atomically, the value pointed to by this immediately before the effects.
7
Remarks: The result may be an undefined address, but the operations otherwise have no undefined
behavior.
T* operator op =(ptrdiff_t operand) volatile noexcept;
T* operator op =(ptrdiff_t operand) noexcept;
8
Effects: Equivalent to: return fetch_key (operand) op operand;
32.6.5
Member operators common to integers and pointers to objects
[atomics.types.memop]
T operator++(int) volatile noexcept;
T operator++(int) noexcept;
Effects: Equivalent to: return fetch_add(1);
T operator--(int) volatile noexcept;
T operator--(int) noexcept;
Effects: Equivalent to: return fetch_sub(1);
T operator++() volatile noexcept;
T operator++() noexcept;
1
Effects: Equivalent to: return fetch_add(1) + 1;
T operator--() volatile noexcept;
T operator--() noexcept;
2
Effects: Equivalent to: return fetch_sub(1) - 1;
32.7
Non-member functions
[atomics.nonmembers]
1
A non-member function template whose name matches the pattern atomic_f or the pattern atomic_f _-
explicit invokes the member function f , with the value of the first parameter as the object expression and
the values of the remaining parameters (if any) as the arguments of the member function call, in order. An
argument for a parameter of type atomic<T>::value_type* is dereferenced when passed to the member
function call. If no such member function exists, the program is ill-formed.
template<class T>
void atomic_init(volatile atomic<T>* object, typename atomic<T>::value_type desired) noexcept;
§ 32.7
1211
template<class T>
void atomic_init(atomic<T>* object, typename atomic<T>::value_type desired) noexcept;
2
Effects: Non-atomically initializes *object with value desired. This function shall only be applied
to objects that have been default constructed, and then only once. [Note: These semantics ensure
compatibility with C. — end note ]
[ Note: Concurrent access from another thread, even via an atomic
operation, constitutes a data race.
— end note ]
3
[Note: The non-member functions enable programmers to write code that can be compiled as either C or
C++, for example in a shared header file.
— end note ]
32.8
Flag type and operations
[atomics.flag]
namespace std {
struct atomic_flag {
bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept;
bool test_and_set(memory_order = memory_order::seq_cst) noexcept;
void clear(memory_order = memory_order::seq_cst) volatile noexcept;
void clear(memory_order = memory_order::seq_cst) noexcept;
atomic_flag() noexcept = default;
atomic_flag(const atomic_flag&) = delete;
atomic_flag& operator=(const atomic_flag&) = delete;
atomic_flag& operator=(const atomic_flag&) volatile = delete;
};
bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;
bool atomic_flag_test_and_set(atomic_flag*) noexcept;
bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept;
bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept;
void atomic_flag_clear(volatile atomic_flag*) noexcept;
void atomic_flag_clear(atomic_flag*) noexcept;
void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept;
void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept;
#define ATOMIC_FLAG_INIT see below
}
1
The atomic_flag type provides the classic test-and-set functionality. It has two states, set and clear.
2
Operations on an object of type atomic_flag shall be lock-free. [ Note: Hence the operations should also be
address-free.
— end note ]
3
The atomic_flag type is a standard-layout struct. It has a trivial default constructor and a trivial destructor.
4
The macro ATOMIC_FLAG_INIT shall be defined in such a way that it can be used to initialize an object of
type atomic_flag to the clear state. The macro can be used in the form:
atomic_flag guard = ATOMIC_FLAG_INIT;
It is unspecified whether the macro can be used in other initialization contexts. For a complete static-duration
object, that initialization shall be static. Unless initialized with ATOMIC_FLAG_INIT, it is unspecified whether
an atomic_flag object has an initial state of set or clear.
bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept;
bool atomic_flag_test_and_set(atomic_flag* object) noexcept;
bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept;
bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept;
bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept;
bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept;
5
Effects: Atomically sets the value pointed to by object or by this to true. Memory is affected
according to the value of order. These operations are atomic read-modify-write operations (6.8.2).
6
Returns: Atomically, the value of the object immediately before the effects.
void atomic_flag_clear(volatile atomic_flag* object) noexcept;
void atomic_flag_clear(atomic_flag* object) noexcept;
void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept;
§ 32.8
1212
void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept;
void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept;
void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept;
7
Requires: The order argument shall not be memory_order::consume, memory_order::acquire, nor
memory_order::acq_rel.
8
Effects: Atomically sets the value pointed to by object or by this to false. Memory is affected
according to the value of order.
32.9
Fences
[atomics.fences]
1
This subclause introduces synchronization primitives called fences. Fences can have acquire semantics, release
semantics, or both. A fence with acquire semantics is called an acquire fence. A fence with release semantics
is called a release fence.
2
A release fence A synchronizes with an acquire fence B if there exist atomic operations X and Y, both
operating on some atomic object M, such that A is sequenced before X, X modifies M, Y is sequenced before
B, and Y reads the value written by X or a value written by any side effect in the hypothetical release
sequence X would head if it were a release operation.
3
A release fence A synchronizes with an atomic operation B that performs an acquire operation on an atomic
object M if there exists an atomic operation X such that A is sequenced before X, X modifies M, and B
reads the value written by X or a value written by any side effect in the hypothetical release sequence X
would head if it were a release operation.
4
An atomic operation A that is a release operation on an atomic object M synchronizes with an acquire fence
B if there exists some atomic operation X on M such that X is sequenced before B and reads the value
written by A or a value written by any side effect in the release sequence headed by A.
extern "C" void atomic_thread_fence(memory_order order) noexcept;
5
Effects: Depending on the value of order, this operation:
(5.1)
has no effects, if order == memory_order::relaxed;
(5.2)
is an acquire fence, if order == memory_order::acquire or order == memory_order::consume;
(5.3)
is a release fence, if order
== memory_order::release;
(5.4)
is both an acquire fence and a release fence, if order == memory_order::acq_rel;
(5.5)
is a sequentially consistent acquire and release fence, if order == memory_order::seq_cst.
extern "C" void atomic_signal_fence(memory_order order) noexcept;
6
Effects: Equivalent to atomic_thread_fence(order), except that the resulting ordering constraints
are established only between a thread and a signal handler executed in the same thread.
7
[Note: atomic_signal_fence can be used to specify the order in which actions performed by the
thread become visible to the signal handler. Compiler optimizations and reorderings of loads and stores
are inhibited in the same way as with atomic_thread_fence, but the hardware fence instructions that
atomic_thread_fence would have inserted are not emitted. — end note ]
§ 32.9
1213
33
Thread support library
[thread]
33.1
General
[thread.general]
1
The following subclauses describe components to create and manage threads (6.8.2), perform mutual exclusion,
and communicate conditions and values between threads, as summarized in Table 140.
Table 140 — Thread support library summary
Subclause
Header(s)
33.2
Requirements
33.3
Threads
<thread>
33.4
Mutual exclusion
<mutex>
<shared_mutex>
33.5
Condition variables
<condition_variable>
33.6
Futures
<future>
33.2
Requirements
[thread.req]
33.2.1
Template parameter names
[thread.req.paramname]
1
Throughout this Clause, the names of template parameters are used to express type requirements. If a
template parameter is named Predicate, operator() applied to the template argument shall return a value
that is convertible to bool.
33.2.2
Exceptions
[thread.req.exception]
1
Some functions described in this Clause are specified to throw exceptions of type system_error (22.5.7).
Such exceptions shall be thrown if any of the function’s error conditions is detected or a call to an operating
system or other underlying API results in an error that prevents the library function from meeting its
specifications. Failure to allocate storage shall be reported as described in 20.5.5.12.
[Example: Consider a function in this clause that is specified to throw exceptions of type system_error
and specifies error conditions that include operation_not_permitted for a thread that does not have the
privilege to perform the operation. Assume that, during the execution of this function, an errno of EPERM
is reported by a POSIX API call used by the implementation. Since POSIX specifies an errno of EPERM
when “the caller does not have the privilege to perform the operation”, the implementation maps EPERM to an
error_condition of operation_not_permitted (22.5) and an exception of type system_error is thrown.
— end example ]
2
The error_code reported by such an exception’s code() member function shall compare equal to one of the
conditions specified in the function’s error condition element.
33.2.3
Native handles
[thread.req.native]
1
Several classes described in this Clause have members native_handle_type and native_handle. The
presence of these members and their semantics is implementation-defined. [Note: These members allow
implementations to provide access to implementation details. Their names are specified to facilitate portable
compile-time detection. Actual use of these members is inherently non-portable.
— end note ]
33.2.4
Timing specifications
[thread.req.timing]
1
Several functions described in this Clause take an argument to specify a timeout. These timeouts are specified
as either a duration or a time_point type as specified in 23.17.
2
Implementations necessarily have some delay in returning from a timeout. Any overhead in interrupt response,
function return, and scheduling induces a “quality of implementation” delay, expressed as duration Di. Ideally,
this delay would be zero. Further, any contention for processor and memory resources induces a “quality of
management” delay, expressed as duration Dm. The delay durations may vary from timeout to timeout, but
in all cases shorter is better.
§ 33.2.4
1214
3
The functions whose names end in _for take an argument that specifies a duration. These functions produce
relative timeouts. Implementations should use a steady clock to measure time for these functions.333 Given a
duration argument Dt, the real-time duration of the timeout is Dt + Di + Dm.
4
The functions whose names end in _until take an argument that specifies a time point. These functions
produce absolute timeouts. Implementations should use the clock specified in the time point to measure time
for these functions. Given a clock time point argument Ct, the clock time point of the return from timeout
should be Ct + Di + Dm when the clock is not adjusted during the timeout. If the clock is adjusted to the
time Ca during the timeout, the behavior should be as follows:
(4.1)
if Ca > Ct, the waiting function should wake as soon as possible, i.e., Ca + Di + Dm, since the timeout
is already satisfied. [Note: This specification may result in the total duration of the wait decreasing
when measured against a steady clock.
— end note ]
(4.2)
if Ca ≤ Ct, the waiting function should not time out until Clock::now() returns a time Cn ≥ Ct, i.e.,
waking at Ct + Di + Dm. [ Note: When the clock is adjusted backwards, this specification may result
in the total duration of the wait increasing when measured against a steady clock. When the clock
is adjusted forwards, this specification may result in the total duration of the wait decreasing when
measured against a steady clock.
— end note ]
An implementation shall return from such a timeout at any point from the time specified above to the time
it would return from a steady-clock relative timeout on the difference between Ct and the time point of the
call to the _until function. [ Note: Implementations should decrease the duration of the wait when the clock
is adjusted forwards.
— end note ]
5
[ Note: If the clock is not synchronized with a steady clock, e.g., a CPU time clock, these timeouts might not
provide useful functionality.
— end note ]
6
The resolution of timing provided by an implementation depends on both operating system and hardware.
The finest resolution provided by an implementation is called the native resolution.
7
Implementation-provided clocks that are used for these functions shall meet the TrivialClock requirements
(23.17.3).
8
A function that takes an argument which specifies a timeout will throw if, during its execution, a clock, time
point, or time duration throws an exception. Such exceptions are referred to as timeout-related exceptions.
[Note: Instantiations of clock, time point and duration types supplied by the implementation as specified
in 23.17.7 do not throw exceptions.
— end note ]
33.2.5
Requirements for Lockable types
[thread.req.lockable]
33.2.5.1
In general
[thread.req.lockable.general]
1
An execution agent is an entity such as a thread that may perform work in parallel with other execution
agents. [ Note: Implementations or users may introduce other kinds of agents such as processes or thread-pool
tasks.
— end note ] The calling agent is determined by context, e.g., the calling thread that contains the
call, and so on.
2
[ Note: Some lockable objects are “agent oblivious” in that they work for any execution agent model because
they do not determine or store the agent’s ID (e.g., an ordinary spin lock).
— end note ]
3
The standard library templates unique_lock (33.4.4.3), shared_lock (33.4.4.4), scoped_lock (33.4.4.2),
lock_guard (33.4.4.1), lock, try_lock (33.4.5), and condition_variable_any (33.5.4) all operate on
user-supplied lockable objects. The BasicLockable requirements, the Lockable requirements, and the
TimedLockable requirements list the requirements imposed by these library types in order to acquire or
release ownership of a lock by a given execution agent. [Note: The nature of any lock ownership and any
synchronization it may entail are not part of these requirements.
— end note ]
33.2.5.2
BasicLockable requirements
[thread.req.lockable.basic]
1
A type L meets the BasicLockable requirements if the following expressions are well-formed and have the
specified semantics (m denotes a value of type L).
333) All implementations for which standard time units are meaningful must necessarily have a steady clock within their
hardware implementation.
§ 33.2.5.2
1215
m.lock()
2
Effects: Blocks until a lock can be acquired for the current execution agent. If an exception is thrown
then a lock shall not have been acquired for the current execution agent.
m.unlock()
3
Requires: The current execution agent shall hold a lock on m.
4
Effects: Releases a lock on m held by the current execution agent.
5
Throws: Nothing.
33.2.5.3
Lockable requirements
[thread.req.lockable.req]
1
A type L meets the Lockable requirements if it meets the BasicLockable requirements and the following
expressions are well-formed and have the specified semantics (m denotes a value of type L).
m.try_lock()
2
Effects: Attempts to acquire a lock for the current execution agent without blocking. If an exception is
thrown then a lock shall not have been acquired for the current execution agent.
3
Return type: bool.
4
Returns: true if the lock was acquired, false otherwise.
33.2.5.4
TimedLockable requirements
[thread.req.lockable.timed]
1
A type L meets the TimedLockable requirements if it meets the Lockable requirements and the following
expressions are well-formed and have the specified semantics (m denotes a value of type L, rel_time denotes
a value of an instantiation of duration (23.17.5), and abs_time denotes a value of an instantiation of
time_point (23.17.6)).
m.try_lock_for(rel_time)
2
Effects: Attempts to acquire a lock for the current execution agent within the relative timeout (33.2.4)
specified by rel_time. The function shall not return within the timeout specified by rel_time unless
it has obtained a lock on m for the current execution agent. If an exception is thrown then a lock shall
not have been acquired for the current execution agent.
3
Return type: bool.
4
Returns: true if the lock was acquired, false otherwise.
m.try_lock_until(abs_time)
5
Effects: Attempts to acquire a lock for the current execution agent before the absolute timeout (33.2.4)
specified by abs_time. The function shall not return before the timeout specified by abs_time unless
it has obtained a lock on m for the current execution agent. If an exception is thrown then a lock shall
not have been acquired for the current execution agent.
6
Return type: bool.
7
Returns: true if the lock was acquired, false otherwise.
33.2.6
decay_copy
[thread.decaycopy]
1
In several places in this Clause the operation DECAY_COPY(x) is used. All such uses mean call the function
decay_copy(x) and use the result, where decay_copy is defined as follows:
template<class T> decay_t<T> decay_copy(T&& v)
{ return std::forward<T>(v); }
33.3
Threads
[thread.threads]
1
33.3 describes components that can be used to create and manage threads. [ Note: These threads are intended
to map one-to-one with operating system threads.
— end note ]
33.3.1
Header <thread> synopsis
[thread.syn]
namespace std {
class thread;
§ 33.3.1
1216
void swap(thread& x, thread& y) noexcept;
namespace this_thread {
thread::id get_id() noexcept;
void yield() noexcept;
template<class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template<class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
}
33.3.2
Class thread
[thread.thread.class]
1
The class thread provides a mechanism to create a new thread of execution, to join with a thread (i.e., wait
for a thread to complete), and to perform other operations that manage and query the state of a thread. A
thread object uniquely represents a particular thread of execution. That representation may be transferred
to other thread objects in such a way that no two thread objects simultaneously represent the same thread
of execution. A thread of execution is detached when no thread object represents that thread. Objects of
class thread can be in a state that does not represent a thread of execution. [ Note: A thread object does
not represent a thread of execution after default construction, after being moved from, or after a successful
call to detach or join.
— end note ]
namespace std {
class thread {
public:
// types
class id;
using native_handle_type = implementation-defined;
// see 33.2.3
// construct/copy/destroy
thread() noexcept;
template<class F, class... Args> explicit thread(F&&
f,
Args&&...
args);
~thread();
thread(const thread&) = delete;
thread(thread&&) noexcept;
thread& operator=(const thread&) = delete;
thread& operator=(thread&&) noexcept;
// members
void swap(thread&) noexcept;
bool joinable() const noexcept;
void join();
void detach();
id get_id() const noexcept;
native_handle_type native_handle();
// see
33.2.3
// static members
static unsigned int hardware_concurrency() noexcept;
};
}
33.3.2.1
Class thread::id
[thread.thread.id]
namespace std {
class thread::id {
public:
id() noexcept;
};
bool operator==(thread::id x, thread::id y) noexcept;
bool operator!=(thread::id x, thread::id y) noexcept;
bool operator<(thread::id x, thread::id y) noexcept;
bool operator<=(thread::id x, thread::id y) noexcept;
§ 33.3.2.1
1217
bool operator>(thread::id x, thread::id y) noexcept;
bool operator>=(thread::id x, thread::id y) noexcept;
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& out, thread::id id);
// hash support
template<class T> struct hash;
template<> struct hash<thread::id>;
}
1
An object of type thread::id provides a unique identifier for each thread of execution and a single distinct
value for all thread objects that do not represent a thread of execution (33.3.2). Each thread of execution has
an associated thread::id object that is not equal to the thread::id object of any other thread of execution
and that is not equal to the thread::id object of any thread object that does not represent threads of
execution.
2
thread::id shall be a trivially copyable class (Clause 12). The library may reuse the value of a thread::id
of a terminated thread that can no longer be joined.
3
[Note: Relational operators allow thread::id objects to be used as keys in associative containers.
— end
note ]
id() noexcept;
4
Effects: Constructs an object of type id.
5
Postconditions: The constructed object does not represent a thread of execution.
bool operator==(thread::id x, thread::id y) noexcept;
6
Returns: true only if x and y represent the same thread of execution or neither x nor y represents a
thread of execution.
bool operator!=(thread::id x, thread::id y) noexcept;
7
Returns: !(x == y)
bool operator<(thread::id x, thread::id y) noexcept;
8
Returns: A value such that operator< is a total ordering as described in 28.7.
bool operator<=(thread::id x, thread::id y) noexcept;
9
Returns: !(y < x).
bool operator>(thread::id x, thread::id y) noexcept;
10
Returns: y < x.
bool operator>=(thread::id x, thread::id y) noexcept;
11
Returns: !(x < y).
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<< (basic_ostream<charT, traits>& out, thread::id id);
12
Effects: Inserts an unspecified text representation of id into out. For two objects of type thread::id
x and y, if x == y the thread::id objects shall have the same text representation and if x != y the
thread::id objects shall have distinct text representations.
13
Returns: out.
template<> struct hash<thread::id>;
14
The specialization is enabled (23.14.15).
§ 33.3.2.1
1218
33.3.2.2
thread constructors
[thread.thread.constr]
thread() noexcept;
1
Effects: Constructs a thread object that does not represent a thread of execution.
2
Postconditions: get_id() == id().
template<class F, class... Args> explicit thread(F&& f, Args&&... args);
3
Requires: F and each Ti in Args shall satisfy the MoveConstructible requirements. INVOKE(DECAY_-
COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...)
(23.14.3) shall be a
valid expression.
4
Remarks: This constructor shall not participate in overload resolution if decay_t<F> is the same type
as std::thread.
5
Effects: Constructs an object of type thread. The new thread of execution executes INVOKE(
DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...) with the calls
to DECAY_COPY being evaluated in the constructing thread. Any return value from this invocation
is ignored.
[Note: This implies that any exceptions not thrown from the invocation of the copy of
f will be thrown in the constructing thread, not the new thread.
— end note ] If the invocation of
INVOKE(DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...) termi-
nates with an uncaught exception, terminate shall be called.
6
Synchronization: The completion of the invocation of the constructor synchronizes with the beginning
of the invocation of the copy of f.
7
Postconditions: get_id() != id(). *this represents the newly started thread.
8
Throws: system_error if unable to start the new thread.
9
Error conditions:
(9.1)
resource_unavailable_try_again — the system lacked the necessary resources to create another
thread, or the system-imposed limit on the number of threads in a process would be exceeded.
thread(thread&& x) noexcept;
10
Effects: Constructs an object of type thread from x, and sets x to a default constructed state.
11
Postconditions: x.get_id() == id() and get_id() returns the value of x.get_id() prior to the start
of construction.
33.3.2.3
thread destructor
[thread.thread.destr]
~thread();
1
If joinable(), calls terminate(). Otherwise, has no effects. [ Note: Either implicitly detaching or
joining a joinable() thread in its destructor could result in difficult to debug correctness (for detach)
or performance (for join) bugs encountered only when an exception is thrown. Thus the programmer
must ensure that the destructor is never executed while the thread is still joinable.
— end note ]
33.3.2.4
thread assignment
[thread.thread.assign]
thread& operator=(thread&& x) noexcept;
1
Effects: If joinable(), calls terminate(). Otherwise, assigns the state of x to *this and sets x to a
default constructed state.
2
Postconditions: x.get_id() == id() and get_id() returns the value of x.get_id() prior to the
assignment.
3
Returns: *this.
33.3.2.5
thread members
[thread.thread.member]
void swap(thread& x) noexcept;
1
Effects: Swaps the state of *this and x.
bool joinable() const noexcept;
2
Returns: get_id() != id().
§ 33.3.2.5
1219
void
join();
3
Effects: Blocks until the thread represented by *this has completed.
4
Synchronization: The completion of the thread represented by *this synchronizes with (6.8.2) the
corresponding successful join() return. [ Note: Operations on *this are not synchronized.
— end
note ]
5
Postconditions: The thread represented by *this has completed. get_id() == id().
6
Throws: system_error when an exception is required (33.2.2).
7
Error conditions:
(7.1)
resource_deadlock_would_occur — if deadlock is detected or get_id() == this_thread::
get_id().
(7.2)
no_such_process — if the thread is not valid.
(7.3)
invalid_argument — if the thread is not joinable.
void
detach();
8
Effects: The thread represented by *this continues execution without the calling thread blocking.
When detach() returns, *this no longer represents the possibly continuing thread of execution. When
the thread previously represented by *this ends execution, the implementation shall release any owned
resources.
9
Postconditions: get_id() == id().
10
Throws: system_error when an exception is required (33.2.2).
11
Error conditions:
(11.1)
no_such_process — if the thread is not valid.
(11.2)
invalid_argument — if the thread is not joinable.
id get_id() const noexcept;
12
Returns: A default constructed id object if *this does not represent a thread, otherwise this_-
thread::get_id() for the thread of execution represented by *this.
33.3.2.6
thread static members
[thread.thread.static]
unsigned hardware_concurrency() noexcept;
1
Returns: The number of hardware thread contexts. [ Note: This value should only be considered to be a
hint.
— end note ] If this value is not computable or well-defined, an implementation should return 0.
33.3.2.7
thread specialized algorithms
[thread.thread.algorithm]
void swap(thread& x, thread& y) noexcept;
1
Effects: As if by x.swap(y).
33.3.3
Namespace this_thread
[thread.thread.this]
namespace std::this_thread {
thread::id get_id() noexcept;
void yield() noexcept;
template<class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template<class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
thread::id this_thread::get_id() noexcept;
1
Returns: An object of type thread::id that uniquely identifies the current thread of execution. No
other thread of execution shall have this id and this thread of execution shall always have this id. The
object returned shall not compare equal to a default constructed thread::id.
§ 33.3.3
1220
void this_thread::yield() noexcept;
2
Effects: Offers the implementation the opportunity to reschedule.
3
Synchronization: None.
template<class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
4
Effects: Blocks the calling thread for the absolute timeout (33.2.4) specified by abs_time.
5
Synchronization: None.
6
Throws: Timeout-related exceptions (33.2.4).
template<class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
7
Effects: Blocks the calling thread for the relative timeout (33.2.4) specified by rel_time.
8
Synchronization: None.
9
Throws: Timeout-related exceptions (33.2.4).
33.4
Mutual exclusion
[thread.mutex]
1
This subclause provides mechanisms for mutual exclusion: mutexes, locks, and call once. These mechanisms
ease the production of race-free programs (6.8.2).
33.4.1
Header <mutex> synopsis
[mutex.syn]
namespace std {
class mutex;
class recursive_mutex;
class timed_mutex;
class recursive_timed_mutex;
struct defer_lock_t { explicit defer_lock_t() = default; };
struct try_to_lock_t { explicit try_to_lock_t() = default; };
struct adopt_lock_t { explicit adopt_lock_t() = default; };
inline constexpr defer_lock_t defer_lock { };
inline constexpr try_to_lock_t try_to_lock { };
inline constexpr adopt_lock_t adopt_lock { };
template<class Mutex> class lock_guard;
template<class... MutexTypes> class scoped_lock;
template<class Mutex> class unique_lock;
template<class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
struct once_flag;
template<class Callable, class... Args>
void call_once(once_flag& flag, Callable&& func, Args&&... args);
}
33.4.2
Header <shared_mutex> synopsis
[shared_mutex.syn]
namespace std {
class shared_mutex;
class shared_timed_mutex;
template<class Mutex> class shared_lock;
template<class Mutex>
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
}
§ 33.4.2
1221

 

 

 

 

 

 

 

Content      ..     39      40      41      42     ..