Multi-threading Library for Standard C++ (Revision 1)

ISO/IEC JTC1 SC22 WG21 N2497=08-0007 - 2008-01-07

Lead author: Howard E. Hinnant

Major contributors: Lawrence Crowl, Beman Dawes, Anthony Williams, Jeff Garland

Other contributors: Hans Boehm, Nick Stoughton, Chris Kohlhoff, PremAnand M Rao, Nathan Myers, Dietmar Kühl, Alisdair Meredith

Contents


Introduction
Chapter 17   Library introduction [library]
        17.1.? blocked thread [defns.thread.blocked]
        17.1.? deadlock [defns.deadlock]
Chapter 20   General utilities library [utilities]
    20.5 Function objects [function.objects]
    20.5.15 Class template hash [unord.hash]
Chapter 30   Multi-threading library [thread]
    30.1 Common Issues [thread.common]
        30.1.1 Template Parameter Names [thread.tmplparmname]
        30.1.2 Exceptions [thread.exception]
        30.1.3 Native Handles [thread.native]
        30.1.4 Timing Specifications [thread.timing_specifications]
    30.2 Threads [thread.threads]
        30.2.1 Class thread [thread.threads.class]
            30.2.1.1 Class thread::id [thread.threads.id]
            30.2.1.2 thread constructors [thread.threads.constr]
            30.2.1.3 thread destructor [thread.threads.destr]
            30.2.1.4 thread assignment [thread.threads.assign]
            30.2.1.5 thread members [thread.threads.member]
            30.2.1.6 thread static members [thread.threads.static]
            30.2.1.7 thread specialized algorithms [thread.threads.algorithm]
        30.2.2 Namespace this_thread [thread.threads.this]
    30.3 Mutual Exclusion [thread.mutex]
        30.3.1 Mutex requirements [thread.mutex.requirements]
            30.3.1.1 Class mutex [thread.mutex.class]
            30.3.1.2 Class recursive_mutex [thread.mutex.recursive]
        30.3.2 TimedMutex requirements [thread.timedmutex.requirements]
            30.3.2.1 Class timed_mutex [thread.timed.class]
            30.3.2.2 Class recursive_timed_mutex [thread.timed.recursive]
        30.3.3 Locks [thread.lock.intro]
            30.3.3.1 Class lock_guard [thread.lock.guard]
            30.3.3.2 Class unique_lock [thread.lock.unique]
        30.3.4 Generic Locking Algorithms [thread.lock.algorithm]
        30.3.5 Call Once [thread.mutex.once]
            30.3.5.1 struct once_flag [thread.mutex.onceflag]
            30.3.5.2 non-member function call_once [thread.threads.callonce]
    30.4 Condition variables [thread.condition]
        30.4.1 Class condition_variable [thread.condvar]
        30.4.2 Class condition_variable_any [thread.condvarany]
Chapter 31   Date Time Library [time]
    31.1 Duration requirements [time.duration.requirements]
    31.2 Class nanoseconds [time.nanoseconds]
    31.3 Class microseconds [time.microseconds]
    31.4 Class milliseconds [time.milliseconds]
    31.5 Class seconds [time.seconds]
    31.6 Class minutes [time.minutes]
    31.7 Class hours [time.hours]
    31.8 Class system_time [time.system]
    31.9 Non-member functions [time.nonmembers]
References
Acknowledgments

Introduction

This paper is a revision of N2447. It incorporates following changes:

This paper uses the following conventions in the HTML source to ease conversion into the format of the working paper.

Chapter 17   Library introduction [library]

Add the following definitions:

17.1.? blocked thread [defns.thread.blocked]

a thread that is waiting for some condition (other than the availability of a processor) to be satisfied before it can continue execution. [Footnote: This definition is taken from POSIX. —end footnote] As a verb, to block is to place a thread in the blocked state, and to unblock is to place a thread in the unblocked state.

17.1.? deadlock [defns.deadlock]

two or more threads are unable to continue execution because each is blocked waiting for one or more of the others to satisfy some condition.

Chapter 20   General utilities library [utilities]

20.5 Function objects [function.objects]

Modify paragraph 2 as follows:

Header functional synopsis


namespace std {
    ...
    // Hash function specializations
    ...
    struct hash<std::thread::id>;
}

20.5.15 Class template hash [unord.hash]

Modify paragraph 1 as follows:

The unordered associative containers defined in clause 23.4 use specializations of hash 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), and std::string, std::u16string, std::u32string, std::wstring, and std::error_code, and std::thread::id.

Chapter 30   Multi-threading library [thread]

The following subclauses describe components to create and manage threads ([intro.multithread]), perform mutual exclusion, and communicate conditions between threads.

Subclause Header(s)
Threads <thread>
Mutual Exclusion <mutex>
Condition variables <condition_variable>

30.1 Common Issues [thread.common]

Unless otherwise stated, the thread-safety requirements of 17.4.3.? ([constraints.?]) and 17.4.4.9 ([res.on.thread.safety]) [Editor: as proposed by N2410 Thread-Safety in the Standard Library (Rev 1) end editor] apply even to types and functions within this clause.

30.1.1 Template Parameter Names [thread.tmplparmname]

Throughout this clause, the names of template parameters are used to express type requirements.

The requirements for Duration parameters are specified in chapter 31 [time].

If a parameter is Predicate, operator() applied to the actual template argument shall return a value that is convertible to bool.

30.1.2 Exceptions [thread.exception]

Implementations of functions described in this clause are permitted to call operating system or other low-level applications program interfaces (API's). Some functions described in this clause are specified to throw exceptions of type system_error ([syserr.syserr]). Such exceptions shall be thrown if such a call results in an error that prevents the library function from satisfying its postconditions or from returning a meaningful value.

The error_category ([syserr.errcat.overview]) of the error_code reported by such an exception's code() member function is implementation-defined. [Note: The category is typically system_category ([syserr.errcat.overview]) since these error codes usually originate from the underlying operating system application program interface (API). —end note]

30.1.3 Native Handles [thread.native]

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]

30.1.4 Timing Specifications [thread.timing_specifications]

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 [time].

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.

30.2 Threads [thread.threads]

This section describes components to create and manage threads.

[Note: These threads are intended to map one-to-one with operating system threads. —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();
    void sleep(const system_time& abs_t);
    template <class Duration>
        void sleep(const Duration& rel_t);

}  // this_thread

}  // std

30.2.1 Class thread [thread.threads.class]

The class thread provides a mechanism to create a new thread of execution, and 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 the 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]


class thread
{
public:
    // types:
    class id;
    typedef implementation-defined native_handle_type; // See [thread.native]

    // construct/copy/destroy:
    thread();
    template <class F> explicit thread(F f);
    template <class F, class ...Args> 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(); // See [thread.native]

    // static members:
    static unsigned hardware_concurrency();
};

Class thread and class thread::id shall be standard-layout classes (chapter 9 [class]).

30.2.1.1 Class thread::id [thread.threads.id]

class thread::id
{
public:
    id();
};

bool operator==(thread::id x, thread::id y);
bool operator!=(thread::id x, thread::id y);
bool operator<(thread::id x, thread::id y);
bool operator<=(thread::id x, thread::id y);
bool operator>(thread::id x, thread::id y);
bool operator>=(thread::id x, thread::id y);

template<class charT, class traits>
basic_ostream<charT, traits>&
operator<< (basic_ostream<charT, traits>&& out, thread::id id);

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 ([thread.threads.class]). Each thread of execution has a thread::id that is not equal to the thread::id of other threads of execution and that is not equal to the thread::id of std::thread objects that do not represent threads of execution.

[Note: Relational operators allows thread::id objects to be used as keys in associative containers. —end note]


id();
Effects:
Constructs an object of type id.
Throws:
Nothing.
Postconditions:
The constructed object does not represent a thread.

bool operator==(thread::id x, thread::id y);
Returns:
Returns true only if x and y represent the same thread of execution or neither x nor y represent a thread of execution.
Throws:
Nothing.

bool operator!=(thread::id x, thread::id y);
Returns:
!(x == y)
Throws:
Nothing.

bool operator<(thread::id x, thread::id y);
Returns:
A value such that operator< is a total ordering as described in [alg.sorting].
Throws:
Nothing.

bool operator<=(thread::id x, thread::id y);
Returns:
!(y < x)
Throws:
Nothing.

bool operator>(thread::id x, thread::id y);
Returns:
y < x
Throws:
Nothing.

bool operator>=(thread::id x, thread::id y);
Returns:
!(x < y)
Throws:
Nothing.

template<class charT, class traits>
basic_ostream<charT, traits>&
operator<< (basic_ostream<charT, traits>&& out, thread::id id);
Effects:
Inserts an unspecified text representation of the thread::id into the stream out. Distinct thread id's shall have distinct representations.
Returns:
out.
30.2.1.2 thread constructors [thread.threads.constr]

thread();
Effects:
Constructs a thread object that does not represent a thread of execution.
Postconditions:
get_id() == id().
Throws:
Nothing.

template <class F> explicit thread(F f);
template <class F, class ...Args> thread(F&& f, Args&&... args);
Requires:
F and each Ti in Args shall be CopyConstructible if an lvalue and otherwise MoveConstructible. INVOKE(f, w1, w2, ..., wN) ([func.require]) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(Args).
Effects:
Constructs an object of type thread and executes INVOKE(f, t1, t2, ..., tN) in a new thread, 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.
Synchronization:

The invocation of the constructor happens before ([intro.multithread]) the invocation of f.

Every thread shall ensure that all its uses of static-duration variables happen before ([intro.multithread ]) their destruction and that all calls to the standard library happen before ([intro.multithread]) completion of destruction of static-duration variables and execution of std::atexit registered functions ([support.start.term]). [Note: Terminating the thread before a call to std::exit or the exit from main is sufficient, but not necessary, to satisfy this requirement. This requirement permits thread managers as static-duration objects. —end note]

Postconditions:
get_id() != id(). *this represents the newly started thread.
Throws:
system_error or bad_alloc if unable to start the new thread.

thread(thread&& x);
Effects:
Constructs an object of type thread from x, and sets x to a default constructed state.
Postconditions:
x.get_id() == id() and get_id() returns the value of x.get_id() prior to the start of construction.
Throws:
Nothing.
30.2.1.3 thread destructor [thread.threads.destr]

~thread();
Effects:
If joinable() then detach(), otherwise no effects. [Note: Destroying a joinable thread can be unsafe if the thread accesses objects or the standard library unless the thread performs explicit synchronization to ensure that it does not access the objects or the standard library past their respective lifetimes. Terminating the process with _exit or quick_exit removes some of these obligations. —end note]
Throws:
Nothing.
30.2.1.4 thread assignment [thread.threads.assign]

thread& operator=(thread&& x);
Effects:
If joinable(), calls detach(). Then assigns the state of x to *this and sets x to a default constructed state.
Postconditions:
x.get_id() == id(), and get_id() returns the value of x.get_id() prior to the assignment.
Throws:
Nothing.
30.2.1.5 thread members [thread.threads.member]

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();
Precondition:
joinable() is true.
Synchronization:
The completion of the thread represented by *this happens before ([intro.multithread]) join() returns. [Note: Operations on *this are not synchronized. —end note]
Postconditions:
If join() throws an exception, the value returned by get_id() remains unchanged. Otherwise get_id() == id().
Throws:
system_error when the postconditions cannot be achieved.

void detach();
Precondition:
joinable() is true.
Effects:
The thread represented by *this continues execution without the current thread blocking. When detach() returns, *this no longer represents the possibly continuing thread of execution. When the thread represented by *this ends execution, the implementation shall release any owned resources.
Postconditions:
get_id() == id().
Throws:
system_error when the effects or postconditions cannot be achieved.

id get_id() const;
Returns:
A default constructed id if *this does not represent a thread, otherwise this_thread::get_id() for the thread of execution represented by *this.
Throws:
Nothing.
30.2.1.6 thread static members [thread.threads.static]

unsigned hardware_concurrency();
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 a return value of 0 is recommended, but not required.
Throws:
Nothing.
30.2.1.7 thread specialized algorithms [thread.threads.algorithm]

void swap(thread&  x, thread&  y);
void swap(thread&& x, thread&  y);
void swap(thread&  x, thread&& y);
Effects:
x.swap(y).

30.2.2 Namespace this_thread [thread.threads.this]


namespace this_thread {

thread::id get_id();

void yield();
void sleep(const system_time& abs_t);
template <class Duration>
    void sleep(const Duration& rel_t);

}  // this_thread

thread::id this_thread::get_id();
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.
Throws:
Nothing.

void yield();
Effects:
Offers the operating system the opportunity to schedule another thread.
Synchronization:
None.
Throws:
Nothing.

void sleep(const system_time& abs_t);
Effects:
The current thread blocks at least until the time specified.
Synchronization:
None.
Throws:
Nothing.

template <class Duration>
    void sleep(const Duration& rel_t);
Effects:
The current thread blocks for at least the amount of time specified. If the resolution of Duration is finer than the native resolution, the time is rounded to the next larger value that can be represented in the native resolution.
Synchronization:
None.
Throws:
Nothing.

30.3 Mutual Exclusion [thread.mutex]

This section provides mechanisms for mutual exclusion: mutexes, locks, and call once. These mechanisms ease the production of race-free programs ([intro.multithread]).

<mutex> synopsis


namespace std {

class mutex;
class recursive_mutex;
class timed_mutex;
class 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&...);

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

30.3.1 Mutex requirements [thread.mutex.requirements]

A mutex object facilitates protection against data races and allows thread-safe synchronization of data between threads. A thread owns a mutex from the time it successfully calls one of the lock functions until it calls unlock. Mutexes may be either recursive or non-recursive, and may grant simultaneous ownership to one or many threads. The mutex types supplied by the Standard Library provide exclusive ownership semantics: only one thread may own the mutex at a time. Both recursive and non-recursive mutexes are supplied.

This section describes requirements on template argument types used to instantiate templates defined in the C++ Standard Library. The template definitions in the C++ Standard Library refer to the named Mutex requirements whose details are set out below. In this description, m is an object of a mutex type.

A mutex type shall be DefaultConstructible and Destructible. If initialization of a mutex type fails, an exception of type system_error shall be thrown. A mutex type is neither copyable nor movable.

The implementation will provide lock and unlock operations, as described below. The implementation shall serialize those operations. [Note: Construction and destruction of a mutex type need not be thread-safe; other synchronization must be used to ensure that mutexes are initialized and visible to other threads. —end note]

The expression m.lock() shall be well-formed, and have the following semantics:

Effects:
The current thread will block until ownership of the mutex can be obtained for the current thread.
Postconditions:
The current thread owns the mutex.
Return type:
void
Synchronization:
Prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Throws:
system_error when the effects or postconditions cannot be achieved.

The expression m.try_lock() shall be well-formed, and have the following semantics:

Effects:
Attempt to obtain ownership of the mutex for the current thread without blocking. If ownership is not obtained, there is no effect and try_lock() immediately returns. An implementation may fail to obtain the lock even if it is not held by any other thread. [Note: This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare_swap ([atomics.operations]). —end note]
Return type:
bool
Returns:
If ownership of the mutex was obtained for the current thread, true, otherwise, false.
Synchronization:
If try_lock returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation. [Note: Since lock() does not synchronize with a failed subsequent try_lock(), the visibility rules are weak enough that little would be known about the state after a failure, even in the absence of spurious failures. —end note]
Throws:
Nothing.

The expression m.unlock() shall be well-formed, and have the following semantics:

Precondition:
The current thread shall own the mutex.
Effects:
Releases the current thread's ownership of the mutex.
Return type:
void
Synchronization:
This operation synchronizes with ([intro.multithread]) subsequent lock operations that obtain ownership on the same object.
Throws:
Nothing.
30.3.1.1 Class mutex [thread.mutex.class]

namespace std {

class mutex
{
public:
    mutex();
    ~mutex();

    mutex(const mutex&) = delete;
    mutex& operator=(const mutex&) = delete;

    void lock();
    bool try_lock();
    void unlock();

    typedef implemenation-defined native_handle_type;  // See [thread.native]
    native_handle_type native_handle();                // See [thread.native]
};

}  // std

The class mutex provides a non-recursive mutex with exclusive ownership semantics. If one thread owns the mutex object, attempts by another thread to acquire ownership will fail (for try_lock()) or block (for lock()) until the first thread has released ownership with a call to unlock().

It satisfies all the Mutex requirements ([thread.mutex.requirements]). It shall be a standard-layout class ([class]).

The behavior of a program is undefined:

30.3.1.2 Class recursive_mutex [thread.mutex.recursive]

namespace std {

class 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 implemenation-defined native_handle_type;  // See [thread.native]
    native_handle_type native_handle();                // See [thread.native]
};

}  // std

The class recursive_mutex provides a recursive mutex with exclusive ownership semantics. If one thread owns the recursive_mutex object, attempts by another thread to acquire ownership will fail (for try_lock()) or block (for lock()) until the first thread has completely released ownership.

It satisfies all the Mutex requirements ([thread.mutex.requirements]). It shall be a standard-layout class ([class]).

A thread that owns a recursive_mutex object may acquire additional levels of ownership by calling lock() or try_lock(). It is unspecified how many levels of ownership may be acquired by a single thread. If a thread has already acquired the maximum level of ownership for a recursive_mutex object, additional calls to try_lock() shall fail, and additional calls to lock() shall throw an exception of type system_error. A thread must call unlock() once for each level of ownership acquired by calls to lock() and try_lock(). Only when all levels of ownership have been released may ownership be acquired by another thread.

The behavior of a program is undefined:

30.3.2 TimedMutex requirements [thread.timedmutex.requirements]

To meet the TimedMutex requirements, types shall meet the Mutex requirements. In addition, the following requirements shall be met, where rel_time denotes a value of a type meeting the Duration ([time.duration]) requirements or abs_time denotes a value of type system_time:

The expression m.timed_lock(rel_time) shall be well-formed, and have the following semantics:

Precondition:
If the resolution of Duration is finer than the native resolution, the time is rounded up to the nearest native resolution.
Effects:
The function attempts to obtain ownership of the mutex within the rel_time time duration. If the rel_time time duration is less than or equal to 0, the function attempts to obtain ownership without blocking (as if by calling try_lock()). The function shall return within the rel_time time duration only if is has obtained ownership of the mutex object. [Note: As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so. —end note]
Return type:
bool
Returns:
true if ownership was obtained, otherwise false.
Synchronization:
If timed_lock returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Throws:
Nothing.

The expression m.timed_lock(abs_time) shall be well-formed, and have the following semantics:

Effects:
The function attempts to obtain ownership of the mutex by the abs_time absolute time. If abs_time has already passed, the function attempts to obtain ownership without blocking (as if by calling try_lock()). The function shall return by the abs_time absolute time only if is has obtained ownership of the mutex object. [Note: As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so. —end note]
Return type:
bool
Returns:
true if ownership was obtained, otherwise false.
Synchronization:
If timed_lock returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Throws:
Nothing.
30.3.2.1 Class timed_mutex [thread.timed.class]

namespace std {

class 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 Duration>
        bool timed_lock(const Duration& rel_time);
    bool timed_lock(const system_time& abs_time);
    void unlock();

    typedef implemenation-defined native_handle_type;  // See [thread.native]
    native_handle_type native_handle();                // See [thread.native]
};

}  // std

The class timed_mutex provides a non-recursive mutex with exclusive ownership semantics. If one thread owns the timed_mutex object, attempts by another thread to acquire ownership will fail (for try_lock()) or block (for lock() and timed_lock()) until the first thread has released ownership with a call to unlock(), or the call to timed_lock() times out (having failed to obtain ownership).

It satisfies all of the TimedMutex requirements ([thread.timedmutex.requirements]). It shall be a standard-layout class (chapter 9 [class]).

The behavior of a program is undefined:

30.3.2.2 Class recursive_timed_mutex [thread.timed.recursive]

namespace std {

class 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 Duration>
        bool timed_lock(const Duration& rel_time);
    bool timed_lock(const system_time& abs_time);
    void unlock();

    typedef implemenation-defined native_handle_type;  // See [thread.native]
    native_handle_type native_handle();                // See [thread.native]
};

}  // std

The class recursive_timed_mutex provides a recursive mutex with exclusive ownership semantics. If one thread owns the recursive_timed_mutex object, attempts by another thread to acquire ownership will fail (for try_lock()) or block (for lock() or timed_lock()) until the first thread has completely released ownership, or the call to timed_lock() times out (having failed to obtain ownership).

It satisfies all of the TimedMutex requirements ([thread.timedmutex.requirements]). It shall be a standard-layout class (chapter 9 [class]).

A thread that owns a recursive_timed_mutex object may acquire additional levels of ownership by calling lock(), try_lock() or timed_lock(). It is unspecified how many levels of ownership may be acquired by a single thread. If a thread has already acquired the maximum level of ownership for a recursive_timed_mutex object, additional calls to try_lock() or timed_lock() shall fail, and additional calls to lock() shall throw an exception of type system_error. A thread must call unlock() once for each level of ownership acquired by calls to lock(), try_lock() and timed_lock(). Only when all levels of ownership have been released may ownership be acquired by another thread.

The behavior of a program is undefined:

30.3.3 Locks [thread.lock.intro]

A lock is an object that holds a reference to a mutex and may unlock the mutex during the lock's destruction (such as when leaving block scope). A thread of execution may use a lock to aid in managing mutex ownership in an exception safe manner. A lock is said to own a mutex if it is currently managing the mutex ownership for a thread of execution. 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 lock constructors may take tag types, which describe what should be done with the mutex during the lock's construction.


struct defer_lock_t  {}; // do not acquire ownership of the mutex
struct try_to_lock_t {}; // try to acquire ownership of the mutex
                         // without blocking
struct adopt_lock_t  {}; // assume the current thread has already
                         // obtained mutex ownership and manage it

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();
};
30.3.3.1 Class lock_guard [thread.lock.guard]

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;

private:
    mutex_type& pm;  // for exposition only
};

}  // std

An object of type lock_guard controls the ownership of a mutex within a scope. A lock_guard object maintains ownership of a mutex throughout the lock_guard's lifetime. The behavior of a program is undefined if the mutex referenced by pm does not exist for the entire lifetime ([basic.life]) of the lock_guard object.


explicit lock_guard(mutex_type& m);
Precondition:
If mutex_type is not a recursive mutex, the current thread does not own mutex m.
Effects:
m.lock().
Postconditions:
&pm == &m.

lock_guard(mutex_type& m, adopt_lock_t);
Precondition:
The current thread owns mutex m.
Postconditions:
&pm == &m.
Throws:
Nothing.

~lock_guard();
Effects:
pm.unlock().
Throws:
Nothing.
30.3.3.2 Class unique_lock [thread.lock.unique]

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(mutex_type& m, const system_time& abs_time);
    template <class Duration>
        unique_lock(mutex_type& m, const Duration& rel_time);
    ~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 Duration>
        bool timed_lock(const Duration& rel_t);
    bool timed_lock(const system_time& abs_time);

    void unlock();

    bool owns_lock() const;
    explicit operator bool () const;
    mutex_type* mutex() const;

    void swap(unique_lock&& u);
    mutex_type* release();

private:
    mutex_type* pm;  // for exposition only
    bool owns;       // for exposition only
};

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

An object of type unique_lock controls the ownership of a mutex within a scope. Mutex ownership may be acquired at construction or subsequent to construction, and subsequent to acquisition may be transferred to another unique_lock object. Objects of type unique_lock are not copyable but are movable. The behavior of a program is undefined if mutex() != 0 and the mutex pointed to by mutex() does not exist for the entire remaining lifetime ([basic.life]) of the unique_lock object.


unique_lock();
Effects:
Constructs an object of type unique_lock.
Postconditions:
pm == 0
owns == false
Throws:
Nothing.

explicit unique_lock(mutex_type& m);
Precondition:
If mutex_type is not a recursive mutex, the current thread does not own the mutex.
Effects:
Constructs an object of type unique_lock, calls m.lock().
Postconditions:
pm == &m
owns == true

unique_lock(mutex_type& m, defer_lock_t);
Precondition:
If mutex_type is not a recursive mutex, the current thread does not own the mutex.
Effects:
Constructs an object of type unique_lock.
Postconditions:
pm == &m
owns == false
Throws:
Nothing.

unique_lock(mutex_type& m, try_to_lock_t);
Precondition:
If mutex_type is not a recursive mutex, then the current thread does not own the mutex.
Effects:
Constructs an object of type unique_lock, calls m.try_lock().
Postconditions:
pm == &m
owns == the result of the call to m.try_lock()
Throws:
Nothing.

unique_lock(mutex_type& m, adopt_lock_t);
Precondition:
The current thread owns mutex m.
Effects:
Constructs an object of type unique_lock.
Postconditions:
pm == &m
owns == true
Throws:
Nothing.

unique_lock(mutex_type& m, const system_time& abs_time);
Precondition:
If mutex_type is not a recursive mutex, then the current thread does not own the mutex.
Effects:
Constructs an object of type unique_lock and calls m.timed_lock(abs_time).
Postconditions:
pm == &m
owns == the result of the call to m.timed_lock(abs_time)
Throws:
Nothing.

template <class Duration>
  unique_lock(mutex_type& m, const Duration& rel_time);
Remarks:
The implementation shall ensure that only Duration types ([time]) will bind to this constructor.
Precondition:
If mutex_type is not a recursive mutex, then the current thread does not own the mutex.
Effects:
Constructs an object of type unique_lock and calls m.timed_lock(rel_time).
Postconditions:
pm == &m
owns == the result of the call to m.timed_lock(rel_time)
Throws:
Nothing.

~unique_lock();
Effects:
If owns calls pm->unlock().
Throws:
Nothing.

unique_lock(unique_lock&& u);
Postconditions:
pm == the value of u.pm prior to establishment of postconditions on u.
owns == the value of u.owns prior to establishment of postconditions on u.
u.pm == 0
u.owns == false
Throws:
Nothing.

unique_lock& operator=(unique_lock&& u);
Effects:
If owns calls pm->unlock().
Postconditions:
pm == the value of u.pm prior to establishment of postconditions on u.
owns == the value of u.owns prior to establishment of postconditions on u.
u.pm == 0
u.owns == false
Throws:
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). —end note]


void lock();
Effects:
pm->lock().
Postconditions:
owns == true
Throws:
lock_error, if on entry owns is true or if pm == 0.

bool try_lock();
Effects:
pm->try_lock().
Returns:
The result of the call to try_lock().
Postconditions:
owns == the result of the call to try_lock().
Throws:
lock_error, if on entry owns is true or if pm == 0.

template <class Duration>
   bool timed_lock(const Duration& rel_t);
Effects:
pm->timed_lock(rel_t).
Returns:
The result of the call to timed_lock(rel_t).
Postconditions:
owns == the result of the call to timed_lock(rel_t).
Throws:
lock_error, if on entry owns is true or if pm == 0.

bool timed_lock(const system_time& abs_t);
Effects:
pm->timed_lock(abs_t).
Returns:
The result of the call to timed_lock(rel_t).
Postconditions:
owns == the result of the call to timed_lock(rel_t).
Throws:
lock_error, if on entry owns is true or if pm == 0.

void unlock();
Effects:
pm->unlock().
Postconditions:
owns == false
Throws:
lock_error, if on entry owns is false.

bool owns_lock() const;
Returns:
owns.
Throws:
Nothing.

explicit operator bool () const;
Returns:
owns.
Throws:
Nothing.

mutex_type* mutex() const;
Returns:
pm.
Throws:
Nothing.

void swap(unique_lock&& u);
Effects:
Swaps each data member of *this with the equivalent data member of u.
Throws:
Nothing.

mutex_type* release();
Returns:
The previous value of pm.
Postconditions:
pm == 0
owns == false
Throws:
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.

30.3.4 Generic Locking Algorithms [thread.lock.algorithm]


template <class L1, class L2, class ...L3> int try_lock(L1&, L2&, L3&...);

Each template parameter type shall meet the Mutex requirements, except that try_lock is allowed to throw an exception. [Note: The unique_lock class template meets these requirements when suitable instantiated. —end note]

Effects:
Calls try_lock() for each argument in order beginning with the first until all arguments have been processed, or a call to try_lock() fails, either by returning false or by throwing an exception. If a call to try_lock() fails, the unlock() function is called for any prior arguments.
Returns:
If all calls to try_lock() returned true, returns -1. Otherwise returns a 0-based index value that indicates the argument for which try_lock() returned false. [Note: On return, either all arguments will be locked or none will be locked. —end note]

template <class L1, class L2, class ...L3> void lock(L1&, L2&, L3&...);

Each template parameter type shall meet the Mutex requirements, except that try_lock is allowed to throw an exception [Note: The unique_lock class template meets these requirements when suitable instantiated. —end note]

Effects:
All arguments are locked via a sequence of calls to lock(), try_lock(), or unlock() on the argument. The sequence of calls shall not result in deadlock, but is otherwise unspecified. [Note: A deadlock avoidance algorithm such as try-and-back-off must be used, but the specific algorithm is not specified to avoid over-constraining implementations. —end note] If an exception is thrown by a call to lock() or try_lock(), then unlock() will be called for any argument that had been locked by a call to lock() or try_lock().

30.3.5 Call Once [thread.mutex.once]

Objects of class once_flag are opaque data structures that allow call_once to initialize data without causing a data race or deadlock.

30.3.5.1 struct once_flag [thread.mutex.onceflag]

constexpr once_flag();
Effects:
Constructs a object of type once_flag.
Synchronization:
The construction of a once_flag is not synchronized.
Postconditions:
Internal state is set to indicate to an invocation of call_once with this once_flag as its initial argument that no function has been called.
30.3.5.2 non-member function call_once [thread.threads.callonce]

template<class Callable, class Args...>
void call_once(once_flag& flag, Callable func, Args&&... args);
Requires:
Callable and each Ti in Args shall be CopyConstructible if an lvalue and otherwise MoveConstructible. INVOKE(func, w1, w2, ..., wN) ([func.require]) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(Args). 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:
Calls to call_once on the same once_flag object are serialized. If there has been a prior effective call_once on the same once_flag object, the call_once returns without invoking func. If there has been no prior effective call_once on the same once_flag object, the argument func (or a copy thereof) is called as-if by invoking func(args). The call_once is effective if and only if func(args) returns without exception. If an exception is thrown, the exception is propagated to the caller.
Synchronization:
The completion of an effective call_once invocation on a once_flag object, synchronizes with ([intro.multithread]) all subsequent call_once invocations on the same once_flag object.
Throws:
system_error when the effects cannot be achieved, or any exception propagated from func.

[Example:


// global flag, regular function

void init();
std::once_flag flag;

void f()
{
    std::call_once(flag,init);
}

// function static flag, function object

struct initializer
{
    void operator()();
};

void g()
{
    static std::once_flag flag2;
    std::call_once(flag2,initializer);
}

// object flag, member function

class information
{
    std::once_flag verified;
    void verifier();
public:
    void verify() { std::call_once(verified,verifier); }
};

end example]

30.4 Condition variables [thread.condition]

Condition variables provide synchronization primitives used to block a thread until notified by some other thread that some condition is met or until a system time is reached. Class condition_variable provides a condition variable that can only wait on a unique_lock<mutex>, allowing maximum efficiency on some platforms. Class condition_variable_any provides a general condition variable that can wait on user supplied lock types.

Condition variables permit concurrent invocation of the wait, timed_wait, notify_one and notify_all member functions.

The execution of notify_one and notify_all shall be atomic. The execution of wait and timed_wait shall be performed in three atomic parts:

  1. The release of the mutex, and entry into the waiting state,
  2. The unblocking of the wait, and
  3. the reacquisition of the lock

The implementation shall behave as though notify_one, notify_all, and each part of the wait and timed_wait executions are executed in some unspecified total order.

Condition variable construction and destruction need not be synchronized.

<condition_variable> synopsis


namespace std {

class condition_variable;
class condition_variable_any;

}  // std

30.4.1 Class condition_variable [thread.condvar]


namespace std {

class condition_variable
{
public:

    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);
    template <class Duration>
        bool timed_wait(unique_lock<mutex>& lock, const Duration& rel_time);
    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);
    template <class Duration, class Predicate>
        bool timed_wait(unique_lock<mutex>& lock, const Duration& rel_time,
                        Predicate pred);

    typedef implemenation-defined native_handle_type;  // See [thread.native]
    native_handle_type native_handle();                // See [thread.native]
};

}  // std

condition_variable shall be a standard-layout class (chapter 9 [class]).


condition_variable();
Effects:
Constructs an object of class condition_variable.

~condition_variable();
Precondition:
There shall be no thread blocked on *this. [Note: That is, all threads shall have been notified; they may subsequently block on the lock specified in the wait. Beware that destructing a condition_variable while the corresponding predicate is false is likely to lead to undefined behavior. —end note]
Effects:
Destroys the object.
Throws:
Nothing.

void notify_one();
Effects:
If any threads are blocked waiting for *this, notify_one unblocks one of those threads.

void notify_all();
Effects:
Unblock all threads that are blocked waiting for *this.

void wait(unique_lock<mutex>& lock);
Precondition:

lock is locked by the current thread, and either:

  • No other thread is waiting on this condition_variable object, or
  • The lock arguments supplied by all concurrently waiting threads (via wait or timed_wait) return the same value for lock.mutex().
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock) and returns.
  • The function will unblock when this thread is signaled by a call to this->notify_one(), a call to this->notify_all(), or spuriously.
  • If the function exits via an exception, lock.lock() will still be called prior to exiting the function scope.
Postconditions:
lock is locked by the current thread.
Throws:
system_error when the effects or postconditions cannot be achieved.

template <class Predicate>
    void wait(unique_lock<mutex>& lock, Predicate pred);
Effects:

As if:


while (!pred())
    wait(lock);

bool timed_wait(unique_lock<mutex>& lock, const system_time& abs_time);
Precondition:

lock is locked by the current thread, and either:

  • No other thread is waiting on this condition_variable object, or
  • The lock arguments supplied by all concurrently waiting threads (via wait or timed_wait) return the same value for lock.mutex().
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock) and returns.
  • The function will unblock when this thread is signaled by a call to this->notify_one(), a call to this->notify_all(), by the current time exceeding abs_time, or spuriously.
  • If the function exits via an exception, lock.lock() will still be called prior to exiting the function scope.
Postconditions:
lock is locked by the current thread.
Returns:
false if the call is returning because the time specified by abs_time was reached, true otherwise.
Throws:
system_error when the returned value, effects or postconditions cannot be achieved.

template <class Duration>
    bool timed_wait(unique_lock<mutex>& lock, const Duration& rel_time);
Effects:

As if:


timed_wait(lock, get_current_time() + rel_time)
Returns:
false if the call is returning because the time duration specified by rel_time has elapsed, true otherwise.

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: The return value indicates whether the predicate evaluates to true, regardless of whether the timeout was triggered. —end note]


template <class Duration, class Predicate>
    bool timed_wait(unique_lock<mutex>& lock, const Duration& rel_time,
                    Predicate pred);
Effects:

As if:


timed_wait(lock, get_system_time() + rel_time, std::move(pred))

[Note: There is no blocking if pred() is initially true, even if the timeout has already expired. —end note]

Returns:

pred().

[Note: The return value indicates whether the predicate evaluates to true, regardless of whether the timeout was triggered. —end note]

30.4.2 Class condition_variable_any [thread.condvarany]

To meet the Lock requirement, types shall meet the Mutex requirement except that try_lock is not required. [Note: All of the standard mutex types meet this requirement. —end note]


namespace std {

class condition_variable_any
{
public:
    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 Duration>
        bool timed_wait(Lock& lock, const Duration& rel_time);
    template <class Lock, class Predicate>
        bool timed_wait(Lock& lock, const system_time& abs_time,
                        Predicate pred);
    template <class Lock, class Duration, class Predicate>
        bool timed_wait(Lock& lock, const Duration& rel_time, Predicate pred);

    typedef implemenation-defined native_handle_type;  // See [thread.native]
    native_handle_type native_handle();                // See [thread.native]
};

}  // std

condition_variable_any();
Effects:
Constructs an object of class condition_variable_any.

~condition_variable_any();
Precondition:
There shall be no thread blocked on *this. [Note: That is, all threads shall of been notified; they may subsequently block on the lock specified in the wait. Beware that destructing a condition_variable while the corresponding predicate is false is likely to lead to undefined behavior. —end note]
Effects:
Destroys the object.
Throws:
Nothing.

void notify_one();
Effects:
If any threads are blocked waiting for *this, unblocks one those threads.

void notify_all();
Effects:
Unblock all threads that are blocked waiting for *this.

template <class Lock>
  void wait(Lock& lock);
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock) and returns.
  • The function will unblock when this thread is signaled by a call to this->notify_one(), a call to this->notify_all(), or spuriously.
  • If the function exits via an exception, lock.lock() will still be called prior to exiting the function scope.
Postconditions:
lock is locked by the current thread.
Throws:
system_error when the effects or postconditions cannot be achieved.

template <class Lock, class Predicate>
    void wait(Lock& lock, Predicate pred);
Effects:

As if:


while (!pred())
    wait(lock);

template <class Lock>
    bool timed_wait(Lock& lock, const system_time& abs_time);
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock) and returns.
  • The function will unblock when this thread is signaled by a call to this->notify_one(), a call to this->notify_all(), by the current time exceeding abs_time, or spuriously.
  • If the function exits via an exception, lock.lock() will still be called prior to exiting the function scope.
Postconditions:
lock is locked by the current thread.
Returns:
false if the call is returning because the time specified by abs_time was reached, true otherwise.
Throws:
system_error when the returned value, effects or postconditions cannot be achieved.

template <class Lock, class Duration>
    bool timed_wait(Lock& lock, const Duration& rel_time);
Effects:

As if:


timed_wait(lock, get_current_time() + rel_time)
Returns:
false if the call is returning because the time duration specified by rel_time has elapsed, true otherwise.

template <class Lock, 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: The return value indicates whether the predicate evaluates to true, regardless of whether the timeout was triggered. —end note]


template <class Lock, class Duration, class Predicate>
    bool timed_wait(Lock& lock, const Duration& rel_time, Predicate pred);
Effects:

As if:


timed_wait(lock, get_system_time() + rel_time, std::move(pred))

[Note: There is no blocking if pred() is initially true, even if the timeout has already expired. —end note]

Returns:

pred().

[Note: The return value indicates whether the predicate evaluates to true, regardless of whether the timeout was triggered. —end note]

Chapter 31   Date Time Library [time]

This clause describes components for determining and manipulating temporal values. A time point represents a dimensionless instant in the time continuum. A time duration represents a length of time unattached to any time point. Time points and time durations have a resolution which is their smallest representable time duration. Time points have an epoch or start of a given time scale. [Example: For std::time_t the epoch is 1970-01-01 00:00:00. —end example]

Throughout this clause, the names of template parameters are used to express type requirements. Parameter names Duration, LhsDuration and RhsDuration express the Duration requirements ([time.duration.requirements]). For all non-member functions in this clause that are templated on Duration types, the implementation shall constrain these function templates such that they will only instantiate for Duration types.

The Duration types shall represent durations of at least ± 292 years. The system_time type shall represent times at least within the range epoch + 292 years.

Header <date_time> Synopsis


namespace std {

// duration types
class nanoseconds;
class microseconds;
class milliseconds;
class seconds;
class minutes;
class hours;

// timepoint type
class system_time;

// non-member functions ([time.nonmembers])
system_time get_system_time();

template<typename Duration>
  system_time operator+(const Duration& td, const system_time& rhs);

template <class LhsDuration, class RhsDuration>
  bool operator==(const LhsDuration& lhs, const RhsDuration& rhs);
template <class LhsDuration, class RhsDuration>
  bool operator!=(const LhsDuration& lhs, const RhsDuration& rhs);

template <class LhsDuration, class RhsDuration>
  bool operator< (const LhsDuration& lhs, const RhsDuration& rhs);
template <class LhsDuration, class RhsDuration>
  bool operator<=(const LhsDuration& lhs, const RhsDuration& rhs);
template <class LhsDuration, class RhsDuration>
  bool operator> (const LhsDuration& lhs, const RhsDuration& rhs);
template <class LhsDuration, class RhsDuration>
  bool operator>=(const LhsDuration& lhs, const RhsDuration& rhs);

template <class LhsDuration, class RhsDuration>
  FinestDuration operator+(const LhsDuration& lhs, const RhsDuration& rhs)
template <class LhsDuration, class RhsDuration>
  FinestDuration operator-(const LhsDuration& lhs, const RhsDuration& rhs)

template <class Duration>
  Duration operator*(Duration lhs, long rhs)
template <class Duration>
  Duration operator*(long lhs, Duration rhs)

template <class Duration>
  Duration operator/(Duration lhs, long rhs)
}  // std

Through this clause, type FinestDuration is whichever of LhsDuration or RhsDuration has the finest resolution. If their resolutions are the same, FinestDuration is LhsDuration.

Unless otherwise specified, no function in this clause shall throw exceptions. [Note: Such blanket prohibition of exceptions is unusual in the standard library, but without the prohibition time-related code becomes littered with excessive try-catch blocks. These functions are also unusual in that they encompass virtually no cases where errors can be detected and reported. —end note]

31.1 Duration requirements [time.duration.requirements]

This subclause describes requirements on duration types used to instantiate templates defined in the C++ Standard Library.

Objects of duration types provide time length values which can be positive or negative. Duration types provide comparison and arithmetic operations on those values.

Template definitions in the C++ Standard Library refer to the named Duration requirements for duration types whose details are specified below.

A duration type E is said to be exactly convertible to another duration type D if and only if:

A duration type shall be EqualityComparable, LessThanComparable, CopyConstructible, DefaultConstructible, CopyAssignable, Swappable, and Destructible. In addition, it must meet the requirements for well-formed expressions specified in the following table, where D and E are duration types, d denotes a value of type D, d0 denotes d.tick_count() at entry into the function, e denotes a const value of type E, c denotes a long value. E shall be exactly convertible to D (diagnostic required).

expression return type return value
D::tick_type implementation defined  
D::ticks_per_second D::tick_type The number of ticks per second, or 0 for types for which the number of ticks per second is less than 1.
D::seconds_per_tick D::tick_type The number of seconds per tick, or 0 for types for which the number of seconds per tick is less than 1.
D::is_subsecond bool seconds_per_tick == 0
d.count() D::tick_type The most recent value established by a non-const function's postcondition.
-d D D(-d.tick_count())
    postcondition
d -= e D& d.tick_count() == d0 - x, where x is e.tick_count() converted to the resolution of D.
d += e D& d.tick_count() == d0 + x, where x is e.tick_count() converted to the resolution of D.
d /= c D& d.tick_count() == d0 / c
d *= c D& d.tick_count() == d0 * c

31.2 Class nanoseconds [time.nanoseconds]

Objects of class nanoseconds can be used to represent a count of nanoseconds.

Class nanoseconds shall be a duration type ([time.duration.requirements]). For the sake of exposition, the semantics of member functions are not described if they have the same apparent semantics as specified for duration types.


class nanoseconds
{
public:
    // traits information
    typedef implementation-defined tick_type;
    static const tick_type ticks_per_second = 1000L * 1000 * 1000;
    static const tick_type seconds_per_tick = 0;
    static const bool is_subsecond = true;

    // construct/copy/destroy functions
    nanoseconds(long long ns=0);

    // observer functions
    tick_type count() const;

    // modifier functions
    template<typename RhsDuration>
        nanoseconds& operator-=(const RhsDuration& d);
    template<typename RhsDuration>
        nanoseconds& operator+=(const RhsDuration& d);
    nanoseconds& operator*=(long multiplier);
    nanoseconds& operator/=(long divisor);

    // operations
    nanoseconds operator-() const;
};

nanoseconds(long long ns=0);
Effects:
Constructs an object of type nanoseconds.
Postcondition:
count() == ns;

31.3 Class microseconds [time.microseconds]

Objects of class microseconds can be used to represent a count of microseconds.

Class microseconds shall be a duration type ([time.duration.requirements]). For the sake of exposition, the semantics of member functions are not described if they have the same apparent semantics as specified for duration types.


class microseconds
{
public:
    // traits information
    typedef implementation-defined tick_type;
    static const tick_type ticks_per_second = 1000L * 1000;
    static const tick_type seconds_per_tick = 0;
    static const bool is_subsecond = true;

    // construct/copy/destroy functions
    microseconds(long long us=0);

    // observer functions
    tick_type count() const;

    // modifier functions
    template<typename RhsDuration>
        microseconds& operator-=(const RhsDuration& d);
    template<typename RhsDuration>
        microseconds& operator+=(const RhsDuration& d);
    microseconds& operator*=(long multiplier);
    microseconds& operator/=(long divisor);

    // operations
    microseconds operator-() const;

    // conversions
    operator nanoseconds() const;
};

microseconds(long long us=0);
Effects:
Constructs an object of type microseconds.
Postcondition:
count() == us;

operator nanoseconds() const;
Returns:
count() * (nanoseconds::ticks_per_second / microseconds::ticks_per_second).

31.4 Class milliseconds [time.milliseconds]

Objects of class milliseconds can be used to represent a count of milliseconds.

Class milliseconds shall be a duration type ([time.duration.requirements]). For the sake of exposition, the semantics of member functions are not described if they have the same apparent semantics as specified for duration types.


class milliseconds
{
public:
    // traits information
    typedef implementation-defined tick_type;
    static const tick_type ticks_per_second = 1000;
    static const tick_type seconds_per_tick = 0;
    static const bool is_subsecond = true;

    // construct/copy/destroy functions
    milliseconds(long long ms=0);

    // observer functions
    tick_type count() const;

    // modifier functions
    template<typename RhsDuration>
        milliseconds& operator-=(const RhsDuration& d);
    template<typename RhsDuration>
        milliseconds& operator+=(const RhsDuration& d);
    milliseconds& operator*=(long multiplier);
    milliseconds& operator/=(long divisor);

    // operations
    milliseconds operator-() const;

    // conversions
    operator nanoseconds() const;
    operator microseconds() const;
};

milliseconds(long long ms=0);
Effects:
Constructs an object of type milliseconds.
Postcondition:
count() == ms;

operator nanoseconds() const;
Returns:
count() * (nanoseconds::ticks_per_second / milliseconds::ticks_per_second).

operator microseconds() const;
Returns:
count() * (microseconds::ticks_per_second / milliseconds::ticks_per_second).

31.5 Class seconds [time.seconds]

Objects of class seconds can be used to represent a count of seconds.

Class seconds shall be a duration type ([time.duration.requirements]). For the sake of exposition, the semantics of member functions are not described if they have the same apparent semantics as specified for duration types.


class seconds
{
public:
    // traits information
    typedef implementation-defined tick_type;
    static const tick_type ticks_per_second = 1;
    static const tick_type seconds_per_tick = 1;
    static const bool is_subsecond = false;

    // construct/copy/destroy functions
    seconds(long long s=0);

    // observer functions
    tick_type count() const;

    // modifier functions
    template<typename RhsDuration>
        seconds& operator-=(const RhsDuration& d);
    template<typename RhsDuration>
        seconds& operator+=(const RhsDuration& d);
    seconds& operator*=(long multiplier);
    seconds& operator/=(long divisor);

    // operations
    seconds operator-() const;

    // conversions
    operator nanoseconds() const;
    operator microseconds() const;
    operator milliseconds() const;
};

seconds(long long s=0);
Effects:
Constructs an object of type seconds.
Postcondition:
count() == s;

operator nanoseconds() const;
Returns:
count() * (seconds::seconds_per_tick * nanoseconds::ticks_per_second).

operator microseconds() const;
Returns:
count() * (seconds::seconds_per_tick * microseconds::ticks_per_second).

operator milliseconds() const;
Returns:
count() * (seconds::seconds_per_tick * milliseconds::ticks_per_second).

31.6 Class minutes [time.minutes]

Objects of class minutes can be used to represent a count of minutes.

Class minutes shall be a duration type ([time.duration.requirements]). For the sake of exposition, the semantics of member functions are not described if they have the same apparent semantics as specified for duration types.


class minutes
{
public:
    // traits information
    typedef implementation-defined tick_type;
    static const tick_type ticks_per_second = 0;
    static const tick_type seconds_per_tick = 60;
    static const bool is_subsecond = false;

    // construct/copy/destroy functions
    minutes(long long m=0);

    // observer functions
    tick_type count() const;

    // modifier functions
    template<typename RhsDuration>
        minutes& operator-=(const RhsDuration& d);
    template<typename RhsDuration>
        minutes& operator+=(const RhsDuration& d);
    minutes& operator*=(long multiplier);
    minutes& operator/=(long divisor);

    // operations
    minutes operator-() const;

    // conversions
    operator nanoseconds() const;
    operator microseconds() const;
    operator milliseconds() const;
    operator seconds() const;
};

minutes(long long m=0);
Effects:
Constructs an object of type minutes.
Postcondition:
count() == m;

operator nanoseconds() const;
Returns:
count() * (minutes::seconds_per_tick * nanoseconds::ticks_per_second).

operator microseconds() const;
Returns:
count() * (minutes::seconds_per_tick * microseconds::ticks_per_second).

operator milliseconds() const;
Returns:
count() * (minutes::seconds_per_tick * milliseconds::ticks_per_second).

operator seconds() const;
Returns:
count() * (minutes::seconds_per_tick / seconds::seconds_per_tick).

31.7 Class hours [time.hours]

Objects of class hours can be used to represent a count of hours.

Class hours shall be a duration type ([time.duration.requirements]). For the sake of exposition, the semantics of member functions are not described if they have the same apparent semantics as specified for duration types.


class hours
{
public:
    // traits information
    typedef implementation-defined tick_type;
    static const tick_type ticks_per_second = 0;
    static const tick_type seconds_per_tick = 3600;
    static const bool is_subsecond = false;

    // construct/copy/destroy functions
    hours(long long h=0);

    // observer functions
    tick_type count() const;

    // modifier functions
    template<typename RhsDuration>
        hours& operator-=(const RhsDuration& d);
    template<typename RhsDuration>
        hours& operator+=(const RhsDuration& d);
    hours& operator*=(long multiplier);
    hours& operator/=(long divisor);

    // operations
    hours operator-() const;

    // conversions
    operator nanoseconds() const;
    operator microseconds() const;
    operator milliseconds() const;
    operator seconds() const;
    operator minutes() const;
};

hours(long long h=0);
Effects:
Constructs an object of type hours.
Postcondition:
count() == h;

operator nanoseconds() const;
Returns:
count() * (hours::seconds_per_tick * nanoseconds::ticks_per_second).

operator microseconds() const;
Returns:
count() * (hours::seconds_per_tick * microseconds::ticks_per_second).

operator milliseconds() const;
Returns:
count() * (hours::seconds_per_tick * milliseconds::ticks_per_second).

operator seconds() const;
Returns:
count() * (hours::seconds_per_tick / seconds::seconds_per_tick).

operator minutes() const;
Returns:
count() * (hours::seconds_per_tick / minutes::seconds_per_tick).

31.8 Class system_time [time.system]

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. [Note: 292 years represents the number of nanoseconds that can be represented in a signed 64 bit integer. —end note]


class system_time
{
public:

    system_time();
    explicit system_time(time_t, nanoseconds ns=0);

    time_t seconds_since_epoch() const;
    nanoseconds nanoseconds_since_epoch() const;

    // traits
    typedef implementation defined tick_type;
    static const tick_type ticks_per_second = nanoseconds::ticks_per_second;
    static const tick_type seconds_per_tick = 0;
    static const bool is_subsecond = true;

    // 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 Duration>
    system_time operator+(const Duration& td) const;

    template<typename Duration>
    system_time& operator+=(const Duration& td);

    template<typename Duration>
    system_time operator-(const Duration& td) const;

    template<typename Duration>
    system_time& operator-=(const Duration& td)
};

system_time();
Effects:
Constructs a system_time object representing the epoch time.

system_time(time_t secs, nanoseconds ns=0);
Effects:
Constructs a system_time time object representing the time point secs + ns / 1,000,000,000 seconds after the epoch.
Remarks:
If the total nanoseconds is greater than 1 second, the seconds are incremented appropriately.

time_t seconds_since_epoch() const;
Returns:
The seconds since the epoch time represented by the current value of *this.

nanoseconds nanoseconds_since_epoch() const;
Returns:
The nanoseconds since the epoch time represented by the current value of *this.

bool operator==(const system_time& rhs) const;
Returns:
True if the time point represented by *this is the same as the time point represented by rhs.

bool operator!=(const system_time& rhs) const;
Returns:
True if the time point represented by *this is not the same as the time point represented by rhs.

bool operator>(const system_time& rhs) const;
Returns:
True if the time point represented by *this is later than the time point represented by rhs.

bool operator>=(const system_time& rhs) const;
Returns:
True if the time point represented by *this is later or the same as the time point represented by rhs.

bool operator<(const system_time& rhs) const;
Returns:
True if the time point represented by *this is earlier than the time point represented by rhs.

bool operator<=(const system_time& rhs) const;
Returns:
True if the time point represented by *this is earlier or the same as the time point represented by rhs.

nanoseconds operator-(const system_time& rhs) const
Returns:
The difference in nanoseconds between the time point represented by *this and the time point represented by rhs.
Remarks:
If *this < rhs, the result will be negative.

template<typename Duration>
  system_time operator+(const Duration& td) const;
Returns:
system_time(*this) += td.

template<typename Duration>
    system_time& operator+=(const Duration& td);
Effects:
Converts td to nanosecond resolution and adds it to the time represented by *this.
Returns:
*this

template<typename Duration>
  system_time operator-(const Duration& td) const;
Returns:
system_time(*this) -= td.

template<typename Duration>
  system_time& operator-=(const Duration& td)
Effects:
Converts td to nanosecond resolution and subtracts it from the time represented by *this.
Returns:
*this

31.9 Non-member functions [time.nonmembers]


system_time get_system_time();
Returns:
The system time as provided by the operating system. [Note: Provides access to the system clock at a resolution as fine as nanoseconds. The actual resolution may vary. —end note] [Note: No error reporting is provided. Hosted implementations ([intro.compliance]) presumably utilize system clock API's that never report errors. —end note]

template<typename Duration>
  system_time operator+(const Duration& td, const system_time& rhs);
Returns:
rhs + td.

template <class LhsDuration, class RhsDuration>
  bool operator==(const LhsDuration& lhs, const RhsDuration& rhs);
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
FinestDuration(lhs.count()) == FinestDuration(rhs.count())

See [time] for description of FinestDuration.

template <class LhsDuration, class RhsDuration>
  bool operator!=(const LhsDuration& lhs, const RhsDuration& rhs);
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
!(lhs==rhs).

template <class LhsDuration, class RhsDuration>
  bool operator< (const LhsDuration& lhs, const RhsDuration& rhs);
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
FinestDuration(lhs.count()) < FinestDuration(rhs.count())

See [time] for description of FinestDuration.

template <class LhsDuration, class RhsDuration>
  bool operator<=(const LhsDuration& lhs, const RhsDuration& rhs);
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
!(rhs<lhs).

template <class LhsDuration, class RhsDuration>
  bool operator> (const LhsDuration& lhs, const RhsDuration& rhs);
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
rhs<lhs.

template <class LhsDuration, class RhsDuration>
  bool operator>=(const LhsDuration& lhs, const RhsDuration& rhs);
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
!(lhs<rhs).

template <class LhsDuration, class RhsDuration>
  FinestDuration operator+(const LhsDuration& lhs, const RhsDuration& rhs)
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
FinestDuration(lhs.count())+FinestDuration(rhs.count())

See [time] for description of FinestDuration.

template <class LhsDuration, class RhsDuration>
  FinestDuration operator-(const LhsDuration& lhs, const RhsDuration& rhs)
Requires:
Either LhsDuration shall be exactly convertible to RhsDuration or RhsDuration shall be exactly convertible to LhsDuration (diagnostic required).
Returns:
FinestDuration(lhs.count())-FinestDuration(rhs.count())

See [time] for description of FinestDuration.

template <class Duration>
  Duration operator*(Duration lhs, long rhs)
Returns:
lhs *= rhs.

template <class Duration>
  Duration operator*(long lhs, Duration rhs)
Returns:
rhs *= lhs.

template <class Duration>
  Duration operator/(Duration lhs, long rhs)
Returns:
lhs /= rhs.

References

Acknowledgments

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. Pete Becker also contributed numerous critiques, suggestions, and comments on the current proposal, which are most appreciated. Jeff Garland contributed the date time portions of the proposal based on the Boost.DateTime Library and his TR2 proposals.