This is a revision of N2320 which removes cancellation/interruption and changes condition variables per the suggestions in N2406. This is the course of a action requested by the combined LWG/Concurrency working groups at the Kona meeting.
Modify paragraph 2 as follows:
Header
functional
synopsisnamespace std { ... // Hash function specializations ... struct hash<std::thread::id>; //should not be in this header file ? }
hash
[unord.hash]The unordered associative containers defined in clause 23.4 use specializations ofhash
as the default hash function. This class template is only required to be instantiable for integer types (3.9.1), floating point types (3.9.1), pointer types (8.3.1), andstd::string
,std::u16string
,std::u32string
,andstd::wstring
, andstd::thread::id
.
The following subclauses describe components to create and manage threads of execution [intro.execution? (N2334)], perform mutual exclusion and locking, and communicate between threads of execution.
Subclause | Header(s) |
Threads | <thread> |
Mutexs and locks | <mutex> |
Condition variables | <cond_var> |
Some functions described in this clause are specified to throw exceptions of type system_error ([syserr.syserr]). The error_category ([syserr.errcat.overview]) of the error_code reported by such exceptions code() member function is implementation-defined. [Note: The category is typically native_category ([syserr.errcat.overview]) since these error codes usually originate from the underlying operating system application program interface (API). -- end note]
<thread> synopsis
namespace std { class thread; void swap(thread& x, thread& y); void swap(thread&& x, thread& y); void swap(thread& x, thread&& y); namespace this_thread { thread::id get_id(); void yield(); template <class TimeDuration> void sleep(const TimeDuration& rel_t); } // this_thread struct once_flag { constexpr once_flag(); once_flag(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete; }; template<class Callable, class ...Args> void call_once(once_flag& flag, Callable func, Args&&... args); } // std
An object of class thread
manages a thread of execution.
It provides a mechanism to create a new thread of execution,
for the current thread of execution to wait for
completion of a thread of execution, and to perform other operations to manage and query the state of the thread of execution.
class thread { public: // types: class id; typedef implementation-defined native_handle_type; // construct/copy/destroy: thread(); template <class F, class ...Args> explicit thread(F f, Args&&... args); ~thread(); thread(const thread&) = delete; thread(thread&&); thread& operator=(const thread&) = delete; thread& operator=(thread&&); // members: void swap(thread&&); bool joinable() const; void join(); void detach(); id get_id() const; native_handle_type native_handle(); // static members: static unsigned hardware_concurrency(); };
Class thread and class thread::id shall be standard-layout types ([?]).
If and only if the thread type is internally represented by a single data structure which can be passed to operating system specific interfaces, there shall be a nested implementation-defined typedef native_handle_type that is an alias to this native type if it is copyable. Otherwise, if the native type is not copyable, it is a pointer to this native type. The implementation shall document whether the native_handle_type typedef is present.
If the nested typedef native_handle_type exists, then there also shall be a member function native_handle() which returns the underlying representation.
class thread::id { public: id(); }; bool operator==(const thread::id& x, const thread::id& y); bool operator!=(const thread::id& x, const thread::id& y); bool operator<(const thread::id& x, const thread::id& y); bool operator<=(const thread::id& x, const thread::id& y); bool operator>(const thread::id& x, const thread::id& y); bool operator>=(const thread::id& x, const thread::id& y); template<class charT, class traits> basic_ostream<charT, traits>& operator<< (basic_ostream<charT, traits>&& out, const thread::id& id);
Objects of type thread::id uniquely identify threads of execution.
id();Effects: Constructs an object of type id which compares equal to other default constructed id objects.
Throws: Nothing.
bool operator==(const thread::id& x, const thread::id& y);Returns: If neither x nor y identifies a thread of execution, returns true. Otherwise if x and y identify the same thread of execution, returns true. Otherwise returns false.
Throws: Nothing.
bool operator!=(const thread::id& x, const thread::id& y);Returns: !(x == y)
Throws: Nothing.
bool operator<(const thread::id& x, const thread::id& y);Returns: a value such that operator< is a total ordering as described in [alg.sorting].
[Note: Defining a comparison operator allows thread::id objects to be used as keys in associative containers. --end note]
Throws: Nothing.
bool operator<=(const thread::id& x, const thread::id& y);Returns: !(y < x)
Throws: Nothing.
bool operator>(const thread::id& x, const thread::id& y);Returns: y < x
Throws: Nothing.
bool operator>=(const thread::id& x, const thread::id& y);Returns: !(x < y)
Throws: Nothing.
template<class charT, class traits> basic_ostream<charT, traits>& operator<< (basic_ostream<charT, traits>&& out, const thread::id& id);Effects: Inserts an unspecified text representation of the thread::id into the stream out.
Returns: out.
thread();Effects: Constructs a thread object not attached to any thread of execution. [Note: This is the state of a thread object after detach or join is successfully called. -- end note]
Postconditions:
get_id() == thread::id() && joinable() == falseRemarks: get_id() returns an identity that refers to not any thread. This identity compares equal to other non-joinable threads, and compares not equal to all other joinable threads.
Throws: Nothing.
template <class F, class ...Args> explicit thread(F f, Args&&... args);Requires: F is a callable type [func.def]. If f is an lvalue, F must be CopyConstructible. If f is an rvalue, F must only be MoveConstructible.
Effects: Constructs an object of type thread and executes INVOKE(f, t1, t2, ..., tN) in a new thread of execution, where t1, t2, ..., tN are the values in args.... Any return value from f is ignored. If f terminates with an uncaught exception, std::terminate() shall be called.
Postconditions:
get_id() != thread::id() && joinable() == true
*this
represents the newly started thread of execution.Throws: system_error if unable to start the new thread of execution.
thread(thread&& x);Effects: Constructs an object of type thread from x.
Postconditions: x.joinable() is false. x.get_id() == thread().get_id(). joinable() returns the value of x.joinable() prior to the start of construction. get_id() returns the value of x.get_id() prior to the start of construction.
Throws: Nothing.
~thread();Effects: If joinable() then detach(), otherwise no effects.
Throws: Nothing.
thread& operator=(thread&& x);Effects: If this currently refers to a joinable thread object, calls detach(). Then assigns the state of x to *this and sets x to a default constructed state.
Postconditions: x.joinable() is false. x.get_id() == thread().get_id(). joinable() returns the value of x.joinable() prior to the assignment. get_id() returns the value of x.get_id() prior to the assignment.
Throws: Nothing.
void swap(thread&& x);Effects: Swaps the state of *this and x.
Throws: Nothing.
bool joinable() const;Returns: get_id() != id().
Throws: Nothing.
void join();Preconditions: joinable() is true.
Effects: The current thread of execution blocks until the thread of execution represented by
*this
completes.Postconditions: After a normal return of join(), joinable() is false. If join() throws an exception, the thread of execution represented by *this remains joinable.
Throws: May throw system_error.
void detach();Preconditions: joinable() is true.
Effects: The thread of execution represented by *this continues execution. When the thread of execution represented by *this ends execution it shall release any owned resources.
Postconditions: joinable() is false. *this does not represent a thread of execution.
Throws: Nothing.
id get_id() const;Returns: An object of type thread::id which identifies the thread of execution represented by *this. If this thread is not joinable() returns a default constructed thread::id.
Throws: Nothing.
native_handle_type native_handle();Returns: The underlying representation of the thread object.
Throws: Nothing.
unsigned hardware_concurrency();Returns: The number of threads of execution that can reasonably be expected to execute concurrently. [Note: This value should only be considered to be a hint. --end note] If this value is not computable or well defined a return value of 1 is recommended, but not required.
Throws: Nothing.
void swap(thread& x, thread& y); void swap(thread&& x, thread& y); void swap(thread& x, thread&& y);Effects: x.swap(y).
namespace this_thread { thread::id get_id(); void yield(); template <class TimeDuration> void sleep(const TimeDuration& rel_t); } // this_thread
thread::id this_thread::get_id();Returns: Returns an object of type thread::id that uniquely identifies the current thread of execution. The object returned shall not compare equal to a default constructed thread::id.
Throws: Nothing.
void yield();Effects: Offers the operating system the opportunity to schedule another thread of execution.
Throws: Nothing.
template <class TimeDuration> void sleep(const TimeDuration& rel_t);Requires: TimeDuration shall be explicitly convertible to nanoseconds.
Effects: The current thread of execution blocks for at least the amount of time specified.
Throws: Nothing.
struct once_flag
Objects of class
once_flag
are opaque data structures that allowcall_once
to initialize data without causing a data race or deadlock.constexpr once_flag();Effects: Constructs a object of type
once_flag
.Postcondition: Internal state is set to indicate to an invocation of
call_once
with thisonce_flag
as its initial argument that no function has been called.
non-member function call_once
template<class Callable, class Args...> void call_once(once_flag& flag, Callable func, Args&&... args);Requires: If the
Callable
argumentfunc
is an lvalue,F
isCopyConstructible
. Otherwise,func
is an rvalue,and F
isMoveConstructible
. Copying or moving (as appropriate) shall have no side effects, and the effect of calling the copy shall be equivalent to calling the original.Effects: The argument
func
(or a copy thereof) is called exactly once for theonce_flag
object specified byflag
, as-if by invokingfunc(args)
,even if
call_once
is called multiple times for the sameonce_flag
object. If multiple calls tocall_once
with the sameonce_flag
object occur in separate threads of execution, only one thread of execution shall callfunc
, and none shall proceed until the call tofunc
has completed. If the invocation offunc
results in an exception being thrown, the exception is propagated to the caller and the effects are as-if this invocation ofcall_once
did not occur.Throws:
system_error
or any exception propagated fromfunc
.Thread safety: Access to the same
once_flag
object by calls tocall_once
from different threads of execution shall not result in a data race or deadlock.[Examples:
std::once_flag flag; void init(); void f() { std::call_once(flag,init); } struct initializer { void operator()(); }; void g() { static std::once_flag flag2; std::call_once(flag2,initializer()); }-- end example]
<mutex> synopsis
namespace std { struct mutex; struct recursive_mutex; struct timed_mutex; struct recursive_timed_mutex; struct defer_lock_t; struct try_to_lock_t; struct adopt_lock_t; extern const defer_lock_t defer_lock; extern const try_to_lock_t try_to_lock; extern const adopt_lock_t adopt_lock; class lock_error; template <class Mutex> class lock_guard; template <class Mutex> class unique_lock; template <class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y); template <class Mutex> void swap(unique_lock<Mutex>&& x, unique_lock<Mutex>& y); template <class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>&& y); 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&...); } // std
Mutex objects provide synchronization operations to avoid data races. A mutex object supports mutual exclusion between threads of execution by limiting its ownership to a single thread of execution. A thread of execution obtains ownership of a mutex object by calling lock() and relinquishes ownership by calling unlock(). The thread of execution that calls lock() for a mutex object shall call unlock(). Mutexes may be either recursive or non-recursive. The syntax is the same for both recursive and non-recursive mutexes, but the semantics differ for the member functions as described below.
A mutex type shall be DefaultConstructible and Destructible. If initialization of a mutex type fails, an exception of type system_error shall be thrown. The destructor of a mutex type shall not exit by an exception. A mutex type is neither copyable nor movable. A mutex type shall have the following member functions:
void lock();Precondition: For non-recursive mutexes the current thread of execution shall not own the mutex.
Effects: The current thread of execution will block until the mutex is not owned by another thread of execution. Upon successful completion, the current thread of execution owns the mutex.
Throws: system_error.
Thread safety: This is an acquire operation.
bool try_lock();Precondition: For non-recursive mutexes the current thread of execution shall not own the mutex.
Effects: If ownership can be obtained without blocking, then ownership is obtained, else there is no effect and try_lock() immediately returns.
Returns: true if ownership was obtained, otherwise false.
Thread safety: This is an acquire operation if try_lock returns true.
Throws: Nothing.
void unlock();Precondition: The current thread of execution shall own the mutex.
Effects: For a non-recursive mutex ownership is released. For a recursive mutex unlock() must be called the same number of times which the mutex was locked (via either lock() or try_lock() or by any other locking function) before ownership is released.
Thread safety: This is a release operation.
Throws: Nothing.
If and only if the mutex type is internally represented by a single data structure which can be passed to operating system specific interfaces, then there shall be a nested implementation-defined typedef native_handle_type that is an alias to this native type if it is copyable, otherwise if the native type is not copyable, is a pointer to this native type. The implementation shall document whether the native_handle_type typedef is present.
If the nested typedef native_handle_type exists, then there also shall be a member function native_handle() which returns native_handle_type. [Example:
class mutex { pthread_mutex_t m; public: typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle() {return &m;} ... };--end example]
If there is no single operating system specific data structure which implements the mutex type, then neither the nested type native_handle_type nor the member function native_handle() shall not be present. [Example: if a recursive_mutex is implemented with both a pthread_mutex_t and a separate lock count, then there will be no native_handle_type. --end example]
Implementations may supply additional implementation defined constructors which allow further customization as afforded by the implementation or its environment.
namespace std { struct mutex { public: mutex(); ~mutex(); mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; void lock(); bool try_lock(); void unlock(); typedef unspecified native_handle_type; // conditionally present. example: pthread_mutex_t* native_handle_type native_handle(); // conditionally present }; } // std
The class mutex is a non-recursive mutex which satisfies all of the Mutex requirements. It shall be a standard-layout type ([?]).
namespace std { struct recursive_mutex { public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock(); void unlock(); typedef unspecified native_handle_type; // conditionally present. example: pthread_mutex_t* native_handle_type native_handle(); // conditionally present }; } // std
The class recursive_mutex shall be a recursive mutex which satisfies all of the Mutex requirements. It shall be a standard-layout type ([?]).
Types that meet the requirements of the Timed Mutex concept also meet the requirements of the Mutex concept and add a single member function:
template <class TimeDuration> bool timed_lock(const TimeDuration& rel_time);Precondition: For non-recursive mutexes the current thread of execution shall not own the mutex. The type TimeDuration provides resolution information (ticks_per_second) that allows conversion of the specified value into the native time resolution.
Effects: The function attempts to obtain ownership of the mutex within the specified time. If the indicated time is less than or equal to 0, the function still attempts to obtain ownership without blocking (as if by calling try_lock()). If the function returns within the specified time duration, it shall have obtained ownership.
Returns: true if ownership was obtained, otherwise false.
Thread safety: This is a synchronization operation.
Throws: Nothing.
namespace std { struct timed_mutex { public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; void lock(); bool try_lock(); template <class TimeDuration> bool timed_lock(const TimeDuration& rel_time); void unlock(); typedef unspecified native_handle_type; // conditionally present. example: pthread_mutex_t* native_handle_type native_handle(); // conditionally present }; } // std
The class timed_mutex is a non-recursive mutex that satisfies all of the Timed Mutex requirements. It shall be a standard-layout type ([?]).
namespace std { struct recursive_timed_mutex { public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); bool try_lock(); template <class TimeDuration> bool timed_lock(const TimeDuration& rel_time); void unlock(); typedef unspecified native_handle_type; // conditionally present. example: pthread_mutex_t* native_handle_type native_handle(); // conditionally present }; } // std
The class recursive_timed_mutex shall be a recursive mutex that satisfies all of the Timed Mutex requirements. It shall be a standard-layout type ([?]).
Locks are objects that hold a reference to a mutex and unlock the mutex during the lock's destruction (such as when leaving block scope). The locks do not manage the lifetime of the mutex they reference, but only the ownership status of that mutex. [Note: Locks are intended to ease the burden of unlocking the mutex under both normal and exceptional circumstances. --end note]
Some locks may take tag types which describe what should be done with the mutex in the lock's constructor.
struct defer_lock_t {}; struct try_to_lock_t {}; struct adopt_lock_t {}; extern const defer_lock_t defer_lock; extern const try_to_lock_t try_to_lock; extern const adopt_lock_t adopt_lock;
An exception class lock_error derives from exception and is used to indicate improper usage of locks such as locking a mutex that the lock already owns, or unlocking a mutex that the lock does not own.
class lock_error : public std::exception { public: virtual const char* what() const throw(); };
namespace std { template <class Mutex> class lock_guard { public: typedef Mutex mutex_type; explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard(); lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; } // std
lock_guard is used to control the ownership of a mutex within a single scope. An invariant of the lock_guard object is that it maintains the ownership of the mutex throughout the lock_guard's lifetime. Mutex ownership can not be deferred or transferred away from the lock_guard.
explicit lock_guard(mutex_type& m);Precondition: If mutex_type is not a recursive mutex, the current thread of execution does not own the mutex. The lifetime of m is greater than the lifetime of the
lock_guard
object.Effects: Stores a reference to m and calls m.lock().
lock_guard(mutex_type& m, adopt_lock_t);Precondition: The current thread of execution has ownership of the mutex m. The lifetime of m is greater than the lifetime of the
lock_guard
object.Effects: Stores a reference to m and performs no other operation on it.
~lock_guard();Effects: m.unlock().
Throws: Nothing.
namespace std { template <class Mutex> class unique_lock { public: typedef Mutex mutex_type; unique_lock(); explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t); unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); ~unique_lock(); unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; unique_lock(unique_lock&& u); unique_lock& operator=(unique_lock&& u); void lock(); bool try_lock(); template <class TimeDuration> bool timed_lock(const TimeDuration& rel_t); bool timed_lock(const system_time& abs_time); void unlock(); bool owns_lock() const; operator unspecified-bool-type () const; mutex_type* mutex() const; void swap(unique_lock&& u); mutex_type* release(); }; template <class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y); template <class Mutex> void swap(unique_lock<Mutex>&& x, unique_lock<Mutex>& y); template <class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>&& y); } // std
unique_lock is used to control the ownership of a mutex within one or more scopes. Mutex ownership can be deferred or transferred away from the unique_lock. An object of type unique_lock is not copyable but is movable.
unique_lock();Effects: Constructs an object of type unique_lock.
Postcondition:
mutex() == 0 owns_lock() == false
explicit unique_lock(mutex_type& m);Precondition: If mutex_type is not a recursive mutex, the current thread of execution does not own the mutex. The lifetime of m is greater than the lifetime of the unique_lock object.
Effects: Stores a reference to m and calls m.lock().
Postcondition:
mutex() == &m owns_lock() == true
unique_lock(mutex_type& m, defer_lock_t);Precondition: If mutex_type is not a recursive mutex, the current thread of execution does not own the mutex. The lifetime of m is greater than the lifetime of the unique_lock object.
Effects: Stores a reference to m and performs no other operation on it.
Postcondition:
mutex() == &m owns_lock() == false
unique_lock(mutex_type& m, try_to_lock_t);Precondition: If mutex_type is not a recursive mutex, then the current thread of execution does not own the mutex. The lifetime of m is greater than the lifetime of the unique_lock object.
Effects: Stores a reference to m and calls m.try_lock().
Postcondition:
mutex() == &m owns_lock() == The result of the call to m.try_lock()
unique_lock(mutex_type& m, adopt_lock_t);Precondition: The current thread of execution has ownership of the mutex m. The lifetime of m is greater than the lifetime of the unique_lock object.
Effects: Stores a reference to m and performs no other operation on it.
Postcondition:
mutex() == &m owns_lock() == true
~unique_lock();Effects: If owns_lock() calls unlock() on the referenced mutex. Otherwise there are no effects.
Throws: Nothing.
unique_lock(unique_lock&& u);Effects: Transfers mutex ownership (if any) from u to this.
Postcondition:
mutex() == The value of u.mutex() prior to the construction. owns_lock() == The value of u.owns_lock() prior to the construction. u.mutex() == 0 u.owns_lock() == falseThrows: Nothing.
unique_lock& operator=(unique_lock&& u);Effects: If owns_lock() calls unlock(), and then transfers mutex ownership (if any) from u to this.
Postcondition:
mutex() == The value of u.mutex() prior to the construction. owns_lock() == The value of u.owns_lock() prior to the construction. u.mutex() == 0 u.owns_lock() == falseThrows: Nothing.
Note: With a recursive mutex it is possible that both this and u own the same mutex before the assignment. In this case, this will own the mutex after the assignment (and u will not), but the mutex's lock count will be decremented by one.
void lock();Effects: Calls lock() on the referenced mutex.
Postcondition: owns_lock() == true.
Throws: lock_error, if on entry owns_lock() is true.
bool try_lock();Effects: Calls try_lock() on the referenced mutex.
Returns: The result of the call to try_lock() on the referenced mutex.
Postcondition: owns_lock() == The result of the call to try_lock() on the referenced mutex.
Throws: lock_error, if on entry owns_lock() is true.
template <class TimeDuration> bool timed_lock(const TimeDuration& rel_t);Effects: Calls timed_lock(rel_t) on the referenced mutex. If the resolution of TimeDuration is greater than the native resolution the time is rounded up to the nearest native resolution.
Returns: The result of the call to timed_lock(rel_t) on the referenced mutex.
Postcondition: owns_lock() == The result of the call to timed_lock(rel_t) on the referenced mutex.
Throws: lock_error, if on entry owns_lock() is true.
void unlock();Effects: Calls void unlock() on the referenced mutex.
Postcondition: owns_lock() == false.
Throws: lock_error, if on entry owns_lock() is false.
bool owns_lock() const;Returns: true if this owns a lock on a referenced mutex, else false.
Throws: Nothing.
operator unspecified-bool-type () const;Returns: Non-null if owns_lock() would return true, else returns null.
Throws: Nothing.
mutex_type* mutex() const;Returns: A pointer to the referenced mutex, or null if there is no referenced mutex.
Throws: Nothing.
void swap(unique_lock&& u);Effects: Swaps state with u.
Throws: Nothing.
mutex_type* release();Returns: A pointer to the referenced mutex, or null if there is no referenced mutex.
Postcondition:
mutex() == 0 owns_lock() == falseThrows: Nothing.
template <class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y); template <class Mutex> void swap(unique_lock<Mutex>&& x, unique_lock<Mutex>& y); template <class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>&& y);Effects: x.swap(y).
Throws: Nothing.
template <class L1, class L2, class ...L3> int try_lock(L1&, L2&, L3&...);Requires: Each template parameter type must supply the following member functions with semantics corresponding to the Mutex concept, except that try_lock is allowed to throw an exception. [Note: The unique_lock class template meets these requirements when suitable instantiated. --end note]
bool try_lock(); void unlock();Effects: The functions attempts to lock all arguments without blocking by calling try_lock() on each of them. If any argument can not be locked, then all arguments which have already been locked will be unlocked. On return, either all arguments will be locked, or none of them will be locked. If an exception is thrown by a call to try_lock(), there are no effects.
Returns: If all arguments were successfully locked, returns
-1
. Otherwise returns a 0-based index value indicating which argument failed to lock.
template <class L1, class L2, class ...L3> void lock(L1&, L2&, L3&...);Requires: Each template parameter type must supply the following member functions with semantics corresponding to the Mutex concept, except that try_lock is allowed to throw an exception [Note: The unique_lock class template meets these requirements when suitable instantiated. --end note]
void lock(); bool try_lock(); void unlock();Effects: All arguments are locked with an algorithm that avoids deadlock. If an exception is thrown by a call to lock() or try_lock(), there are no effects.
namespace std { class condition_variable; class condition_variable_any; } // std
An object of class condition_variable is a synchronization primitive used to cause a thread of execution to wait until notified by some other thread of execution that some condition is met, or a UTC[(?)] time is reached.
If and only if the condition variable type is internally represented by an object which can be passed to operating system specific interfaces, then there shall be a implementation-defined member typedef native_handle_type that is an alias to this native type, if it is copyable, or if the native type is not copyable, a pointer to this native type. The implementation shall document whether the native_handle_type member typedef is present.
If the nested typedef native_handle_type exists, then there also shall be a member function native_handle() which returns the underlying representation.
namespace std { class condition_variable { public: typedef implementation-defined native_handle_type; condition_variable(); ~condition_variable(); condition_variable(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete; void notify_one(); void notify_all(); void wait(unique_lock<mutex>& lock); template <class Predicate> void wait(unique_lock<mutex>& lock, Predicate pred); bool timed_wait(unique_lock<mutex>& lock, const system_time& abs_time); template <class Predicate> bool timed_wait(unique_lock<mutex>& lock, const system_time& abs_time, Predicate pred); native_handle_type native_handle(); }; } // std
condition_variable();Effects: Constructs an object of class condition_variable.
~condition_variable();Effects: Destroys the object.
Throws: Nothing.
void notify_one();Effects: If any threads of execution are blocked waiting for
*this
, unblocks at least one those threads of execution.Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable object from different threads of execution shall not result in data races or deadlocks.
void notify_all();Effects: Unblock all threads of execution that are blocked waiting for
*this
.Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable object from different threads of execution shall not result in data races or deadlocks.
void wait(unique_lock<mutex>& lock);Precondition: lock is locked by the current thread of execution. No other thread of execution is waiting on this condition_variable object unless lock refers to the same underlying mutex object.
Effects: Atomically blocks and releases the lock on lock. If the wait should throw an exception for any reason, lock will be locked as the exception propagates. This thread of execution shall unblock when another threadof execution issues a notification to this blocked thread of execution. The current thread of execution may unblock and return even in the absence of a notification.
Postcondition: lock is locked by the current thread of execution.
Throws: May throw system_error if a precondition is not met.
Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable object from different threads of execution shall not result in data races or deadlocks.
template <class Predicate> void wait(unique_lock<mutex>& lock, Predicate pred);Effects: While pred() returns false calls wait(lock).
Note: There is no blocking if pred() is initially true.
bool timed_wait(unique_lock<mutex>& lock, const system_time& abs_time);Precondition: The lock is locked by the current thread of execution. No other thread of execution is waiting on this condition_variable object unless lock refers to, the same underlying mutex object.
Effects: Atomically blocks and releases the lock on lock. If the timed_wait should throw an exception for any reason, lock will be locked as the exception propagates out. If the absolute time specified by abs_time passes (that is, system time equals or exceeds abs_time) before the condition_variable is notified, or if the absolute time specified by abs_time has already been passed at the time of the call, then false is returned. This thread of execution shall unblock when another thread of execution issues a notification to this blocked thread of execution. The current thread of execution may unblock and return even in the absence of a notification.
Postcondition: lock is locked by the current thread of execution.
Returns: true if the call to timed_wait is notified prior to the indicated timeout, otherwise returns false.
Throws: May throw system_error if a precondition is not met.
Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable object from different threads of execution shall not result in data races or deadlocks.
template <class Predicate> bool timed_wait(unique_lock<mutex>& lock, const system_time& abs_time, Predicate pred);Effects: As if:
while (!pred()) { if (!timed_wait(lock, abs_time)) return pred(); } return true;Returns: pred().
Note: There is no blocking if pred() is initially true, even if the timeout has already expired. The return value indicates whether the predicate evaluates to true, regardless of whether the timeout was triggered.
native_handle_type native_handle();Returns: the representation of the underlying object used to implement *this.
condition_variable shall be a standard-layout type ([?]).
An object of class condition_variable_any is a synchronization primitive used to cause a thread of execution to wait until notified by some other thread of execution that some condition is met, or a UTC[(?)] time is reached.
The Lock type must support member functions lock and unlock with the semantics of the mutex concept. All of the standard mutex types meet this requirement.
If and only if the condition_variable_any type is internally represented by an an object or objects which can be passed to operating system specific interfaces, then there shall be a nested implementation-defined typedef native_handle_type that is an alias to a type providing access to the object or objects. The type native_handle_type must be copyable; if the object or objects are not copyable, native_handle_type must be a pointer type. The implementation shall document whether the native_handle_type typedef is present.
If the nested typedef native_handle_type exists, then there also shall be a member function native_handle() which returns the underlying representation.
namespace std { class condition_variable_any { public: typedef implementation-defined native_handle_type; condition_variable_any(); ~condition_variable_any(); condition_variable_any(const condition_variable_any&) = delete; condition_variable_any& operator=(const condition_variable_any&) = delete; void notify_one(); void notify_all(); template <class Lock> void wait(Lock& lock); template <class Lock, class Predicate> void wait(Lock& lock, Predicate pred); template <class Lock> bool timed_wait(Lock& lock, const system_time& abs_time); template <class Lock, class Predicate> bool timed_wait(Lock& lock, const system_time& abs_time, Predicate pred); native_handle_type native_handle(); }; } // std
condition_variable_any();Effects: Constructs an object of class condition_variable_any.
~condition_variable_any();Effects: Destroys the object.
Throws: Nothing.
void notify_one();Effects: If any threads of execution are blocked waiting for
*this
, unblocks at least one those threads of execution.Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable_any object from different threads of execution shall not result in data races or deadlocks.
void notify_all();Effects: Unblock all threads of execution that are blocked waiting for
*this
.Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable_any object from different threads of execution shall not result in data races or deadlocks.
void wait(Lock& lock);Precondition: lock is locked by the current thread of execution. If Lock supports recursive locking, the lock count is one. No other thread of execution is waiting on this condition_variable_any object unless lock is, or refers to, the same underlying mutex object.
Effects: Atomically blocks and releases the lock on lock. If the wait should throw an exception for any reason, lock will be locked as the exception propagates. This thread of execution shall unblock when another thread of execution issues a notification to this blocked thread of execution. The current thread of execution may unblock and return even in the absence of a notification.
Postcondition: lock is locked by the current thread of execution.
Throws: May throw system_error.
Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable_any object from different threads of execution shall not result in data races or deadlocks.
template <class Predicate> void wait(lock_type& lock, Predicate pred);Effects: While pred() returns false, calls wait(lock).
Note: There is no blocking if pred() is initially true.
bool timed_wait(Lock& lock, const system_time& abs_time);Precondition: The lock is locked by the current thread of execution. If Lock supports recursive locking, the lock count is one. No other thread of execution is waiting on this condition_variable_any object unless lock is, or refers to, the same underlying mutex object.
Effects: Atomically blocks and releases the lock on lock. If the timed_wait should throw an exception for any reason, lock will be locked as the exception propagates out. If the absolute time specified by abs_time passes (that is, system time equals or exceeds abs_time) before the condition_variable_any is notified, or if the absolute time specified by abs_time has already been passed at the time of the call, then false is returned. This thread of execution shall unblock when another thread of execution issues a notification to this blocked thread of execution. The current thread of execution may unblock and return even in the absence of a notification.
Postcondition: lock is locked by the current thread of execution.
Returns: true if the call to timed_wait is notified prior to the indicated timeout, otherwise returns false.
Throws: May throw system_error.
Thread safety: Calls to the
wait
,timed_wait
,notify_one
ornotify_all
member functions of the same condition_variable_any object from different threads of execution shall not result in data races or deadlocks.
template <class _Predicate> bool timed_wait(Lock& lock, const system_time& abs_time, Predicate pred);Effects: As if:
while (!pred()) { if (!timed_wait(lock, abs_time)) return pred(); } return true;Returns: pred().
Note: There is no blocking if pred() is initially true, even if the timeout has already expired. The return value indicates whether the predicate evaluates to true, regardless of whether the timeout was triggered.
native_handle_type native_handle();Returns: the representation of the underlying object or objects used to implement *this.
namespace std { //duration types class hours; class minutes; class seconds; class milliseconds; class microseconds; class nanoseconds; //timepoint class system_time; //functions system_time get_system_time(); } //std
The class system_time provides a time point that represents the current Coordinated Universal Time, known as UTC, time. system_time shall provide an epoch time of 1970-01-01 00:00:00.000000000 and a maximum time value of at least epoch time + 292 years.
class system_time shall be EqualityComparable, LessThanComparable, CopyConstructable, DefaultConstructable, and Assignable.
class system_time { public: system_time(); system_time(time_t, nanoseconds ns); ~system_time(); time_t seconds_since_epoch() const; nanoseconds nanoseconds_since_epoch() const; //traits typedef 'implementation defined' tick_type; static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); //comparison functions bool operator==(const system_time& rhs) const; bool operator!=(const system_time& rhs) const; bool operator>(const system_time& rhs) const; bool operator>=(const system_time& rhs) const; bool operator<(const system_time& rhs) const; bool operator<=(const system_time& rhs) const; //arithmetic functions nanoseconds operator-(const system_time& rhs) const template<typename TimeDuration> system_time operator+(const TimeDuration& td) const; template<typename TimeDuration> system_time& operator+=(const TimeDuration& td); template<typename TimeDuration> system_time operator-(const TimeDuration& td) const; template<typename TimeDuration> system_time& operator-=(const TimeDuration& td) };
Note
292 years represents the number of nanoseconds that can be represented in a signed 64 bit integer.
system_time();
Effects: Constructs a system_time object representing the epoch time point 1970-01-01 00:00:00.000000000
Throws: Nothing.
system_time(time_t secs, nanoseconds ns);
Effects: Constructs a utc time object representing the time point that is secs + 1,000,000,000*ns after the epoch.
Remarks: If the total nanoseconds > 1 second the seconds are incremented appropriately.
Throws: Nothing.
time_t seconds_since_epoch() const;
Returns: The count of seconds since 1970-01-01 00:00:00.
Throws: Nothing.
nanoseconds nanoseconds_since_epoch() const;
Returns: The count of nanoseconds since 1970-01-01 00:00:00.
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 1000000000
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 0
Remarks: Since this is a subsecond type it returns 0 for seconds_per_tick.
Throws: Nothing.
static bool is_subsecond();
Returns: true.
Throws: Nothing.
bool operator==(const system_time& rhs) const;
Returns: True if the time represented by *this is equal to the time represented by rhs.
Throws: Nothing.
bool operator!=(const system_time& rhs) const;
Returns: True if the time represented by *this is not equal to the time represented by rhs
Throws: Nothing.
bool operator>(const system_time& rhs) const;
Returns: True if time represented by *this is greater than the time represented by rhs.
Throws: Nothing.
bool operator>=(const system_time& rhs) const;
Returns: True if time represented by *this is greater or equal than the time represented by rhs.
Throws: Nothing.
bool operator<(const system_time& rhs) const;
Returns: True if time represented by *this is less than the time represented by rhs.
Throws: Nothing.
bool operator<=(const system_time& rhs) const;
Returns: True if time represented by *this is less or equal than the time represented by rhs.
Throws: Nothing.
nanoseconds operator-(const system_time& rhs) const
Returns: The difference in nanoseconds between the time represented by *this and the time represented by rhs.
Remarks: If rhs is greater the result will be a negative nanosecond. count.
Throws: Nothing.
template<typename TimeDuration> system_time operator+(const TimeDuration& td) const;
Returns: The duration converted to nanosecond resolution and added to the time represented by *this.
Throws: Nothing.
template<typename TimeDuration> system_time& operator+=(const TimeDuration& td);
Effects: Convert the duration to nanosecond resolution add to nanoseconds to the time represented by *this.
Returns: Modified value of this.
Throws: Nothing.
template<typename TimeDuration> system_time operator-(const TimeDuration& td) const;
Returns: The duration converted to nanosecond resolution and subtracted from the time represented by *this.
Throws: Nothing.
template<typename TimeDuration> system_time& operator-=(const TimeDuration& td)
Effects: Convert the duration to nanosecond resolution subtract and from the time represented by *this.
Returns: Modified value of this.
Throws: Nothing.
The function get_system_time provides access to the system clock at a resolution up to nanoseconds. The actual resolution may vary from platform to platform.
system_time get_system_time();
Comment (not for inclusion in WP)
Typical personal computer platforms currently achieve microsecond level resolution from calls to the clock. The Boost Date-Time Library has a class that portably implements the proposed interface, but it uses different C-level interfaces depending on the operating system.
The following functions are common functions to all durations types. These functions provide the basis for durations to be EqualityComparable, LessThanComparable as well arithmetic operations.
In the following text duration_type refers to the containing duration type.
All duration types are EqualityComparable, LessThanComparable, CopyConstructable, DefaultConstructable, and Assignable for duration objects of the same type.
class TimeDuration { //comparison operators template<typename RhsTimeDuration> bool operator< (const RhsTimeDuration&) const; template<typename RhsTimeDuration> bool operator<= (const RhsTimeDuration&) const; template<typename RhsTimeDuration> bool operator> (const RhsTimeDuration&) const; template<typename RhsTimeDuration> bool operator>= (const RhsTimeDuration&) const; template<typename RhsTimeDuration> bool operator== (const RhsTimeDuration&) const; template<typename RhsTimeDuration> bool operator!= (const RhsTimeDuration&) const; //sign inversion TimeDuration operator-() const //arithmetic operations template<typename RhsTimeDuration> TimeDuration operator- (const RhsTimeDuration& d) const template<typename RhsTimeDuration> TimeDuration operator-=(const RhsTimeDuration& d) template<typename RhsTimeDuration> TimeDuration operator+ (const RhsTimeDuration& d) const template<typename RhsTimeDuration> TimeDuration operator+=(const RhsTimeDuration& d) TimeDuration operator/ (int divisor) const TimeDuration operator/=(int divisor) TimeDuration operator* (int rhs) const TimeDuration operator*=(int divisor) tick_type get_count() const }
template<typename RhsTimeDuration> bool operator==(const RhsTimeDuration& rhs) const;
Returns: True if rhs duration is greater.
Throws: Nothing.
template<typename RhsTimeDuration> bool operator!=(const RhsTimeDuration& rhs) const;
Returns: True if rhs is not the same time.
Throws: Nothing.
template<typename RhsTimeDuration> bool operator>(const RhsTimeDuration& rhs) const;
Returns: True if the rhs duration is larger.
Throws: Nothing.
template<typename RhsTimeDuration> bool operator>=(const RhsTimeDuration& rhs) const;
Returns: True if greater or equal than the rhs duration.
Throws: Nothing.
template<typename RhsTimeDuration> bool operator<(const RhsTimeDuration& rhs) const;
Returns: True if less than the rhs duration.
Throws: Nothing.
template<typename RhsTimeDuration> bool operator<=(const RhsTimeDuration& rhs) const;
Returns: True if less or equal to the rhs duration.
Throws: Nothing.
//sign inversion TimeDuration operator-() const
Returns: Negated value of the duration.
Throws: Nothing.
//arithmetic operations template<typename RhsTimeDuration> TimeDuration operator- (const RhsTimeDuration& d) const
Returns: A duration value equal to this-rhs_duration.
Remarks: This will fail to compiler if the RhsTimeDuration is of higher resolution.
Throws: Nothing.
template<typename RhsTimeDuration> TimeDuration operator-=(const RhsTimeDuration& d)
Effects: Modifies to value equal to this-rhs_duration.
Returns: this
Remarks: This will fail to compiler if the RhsTimeDuration is of higher resolution.
Throws: Nothing.
template<typename RhsTimeDuration> TimeDuration operator+ (const RhsTimeDuration& d) const
Returns: Duration equal to this+rhs_duration.
Remarks: This will fail to compiler if the RhsTimeDuration is of higher resolution.
Throws: Nothing.
template<typename RhsTimeDuration> TimeDuration operator+=(const RhsTimeDuration& d)
Effects: Modifies to value equal to this+rhs_duration.
Returns: this
Remarks: This will fail to compiler if the RhsTimeDuration is of higher resolution.
Throws: Nothing.
TimeDuration operator/ (int divisor) const
Returns: Duration with value equal to this/divisor according to integer arithmetic rules.
Throws: Nothing.
TimeDuration operator/=(int divisor)
Effects: Change value of this by this/divisor according to integer arithmetic rules.
Returns: this
Throws: Nothing.
TimeDuration operator* (int rhs) const
Returns: Duration with value equal to this*rhs
Throws: Nothing.
TimeDuration operator*=(int rhs)
Effects: Modifies to value equal to this*rhs.
Returns: this
Throws: Nothing.
tick_type get_count() const
Returns: The count at the resolution of the time duration type.
Throws: Nothing.
Objects of class nanoseconds can be used to represent a count of nanoseconds.
class nanoseconds { public: nanoseconds(long long=0); nanoseconds(const nanoseconds& rhs); ~nanoseconds(); //traits information static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); typedef implementation-defined tick_type; //+ common functions };
nanoseconds(long long=0);
Effects: Constructs an object with a count of nanoseconds - default is zero.
Throws: Nothing.
nanoseconds(const nanoseconds& rhs);
Effects: Copy construction.
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 1000000000
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 0
Throws: Nothing.
static bool is_subsecond();
Returns: true
Throws: Nothing.
Objects of class microseconds can be used to represent a count of microseconds.
class microseconds { public: microseconds(long long=0); microseconds(const microseconds& rhs); ~microseconds(); //conversions operator nanoseconds() const //traits information static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); typedef implementation-defined tick_type; //+ common functions };
microseconds(long long=0);
Effects: Constructs an object with a count of microseconds - default is zero.
Throws: Nothing.
microseconds(const microseconds& rhs);
Effects: Copy construction.
Throws: Nothing.
//conversions operator nanoseconds() const
Returns: microsecond count converted to nanoseconds
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 1000000
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 0
Throws: Nothing.
static bool is_subsecond();
Returns: true
Throws: Nothing.
Objects of class milliseconds can be used to represent a count of milliseconds.
class milliseconds { public: milliseconds(long long=0); milliseconds(const milliseconds& rhs); ~milliseconds(); //conversions operator nanoseconds() const; operator microseconds() const; //traits information static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); typedef implementation-defined tick_type; //+ common functions };
milliseconds(long long=0);
Effects: Constructs an object with a count of milliseconds - default is zero.
Throws: Nothing.
milliseconds(const milliseconds& rhs);
Effects: Copy construction.
Throws: Nothing.
operator nanoseconds() const
Returns: millisecond count converted to nanoseconds
Throws: Nothing.
operator microseconds() const
Returns: millisecond count converted to microseconds
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 1000
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 0
Throws: Nothing.
static bool is_subsecond();
Returns: true
Throws: Nothing.
Objects of class seconds can be used to represent a count of seconds.
class seconds { public: seconds(long long s=0); seconds(const seconds& rhs); ~seconds(); //conversions operator nanoseconds() const operator microseconds() const operator milliseconds() const //traits information static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); typedef implementation-defined tick_type; //+ common functions };
seconds(long long=0);
Effects: Constructs an object with a count of seconds - default is zero.
Throws: Nothing.
seconds(const seconds& rhs);
Effects: Copy construction.
Throws: Nothing.
operator nanoseconds() const
Returns: second count converted to nanoseconds
Throws: Nothing.
operator microseconds() const
Returns: second count converted to microseconds
Throws: Nothing.
operator milliseconds() const
Returns: second count converted to milliseconds
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 1
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 1
Throws: Nothing.
static bool is_subsecond();
Returns: false
Throws: Nothing.
Objects of class minutes can be used to represent a count of minutes.
class minutes { public: minutes(long long s=0); minutes(const minutes& rhs); ~minutes(); //conversions operator nanoseconds() const operator microseconds() const operator milliseconds() const operator seconds() const //traits information static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); typedef implementation-defined tick_type; //+ common functions };
minutes(long long=0);
Effects: Constructs an object with a count of minutes - default is zero.
Throws: Nothing.
minutes(const minutes& rhs);
Effects: Copy construction.
Throws: Nothing.
operator nanoseconds() const
Returns: minute count converted to nanoseconds
Throws: Nothing.
operator microseconds() const
Returns: minute count converted to microseconds
Throws: Nothing.
operator milliseconds() const
Returns: minute count converted to milliseconds
Throws: Nothing.
operator seconds() const
Returns: minute count converted to seconds
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 0
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 60
Throws: Nothing.
static bool is_subsecond();
Returns: false
Throws: Nothing.
Objects of class hours can be used to represent a count of hours.
class hours { public: hours(long long s=0); hours(const hours& rhs); ~hours(); //conversions operator nanoseconds() const operator microseconds() const operator milliseconds() const operator seconds() const operator minutes() const //traits information static tick_type ticks_per_second(); static tick_type seconds_per_tick(); static bool is_subsecond(); typedef implementation-defined tick_type; //+ common functions };
hours(long long=0);
Effects: Constructs an object with a count of hours - default is zero.
Throws: Nothing.
hours(const hours& rhs);
Effects: Copy construction.
Throws: Nothing.
operator nanoseconds() const
Returns: hour count converted to nanoseconds
Throws: Nothing.
operator microseconds() const
Returns: hour count converted to microseconds
Throws: Nothing.
operator milliseconds() const
Returns: hour count converted to milliseconds
Throws: Nothing.
operator seconds() const
Returns: hour count converted to seconds
Throws: Nothing.
operator minutes() const
Returns: hour count converted to seconds.
Throws: Nothing.
static tick_type ticks_per_second();
Returns: 0
Throws: Nothing.
static tick_type seconds_per_tick();
Returns: 3600
Throws: Nothing.
static bool is_subsecond();
Returns: false
Throws: Nothing.
The overall design of this threading library is based on William Kempf's Boost.Thread Library, as refined by literally hundreds of other Boost users and contributors. Dinkumware and Metrowerks (now Freescale) implementations of Boost.Thread, developed respectively by Pete Becker and Howard Hinnant, created further existing practice. Proposals by Pete Becker, Peter Dimov, Ion Gazta�aga, and Anthony Williams were also influential. Peter, Ion, and Anthony also contributed numerous critiques, suggestions, and comments on the current proposal, as did other members of an ad hoc threads working group. Jeff Garland contributed the date time portions of the proposal based on the Boost.DateTime Library and his TR2 proposals.