33 Concurrency support library [thread]

33.2 Requirements [thread.req]

33.2.5 Requirements for Cpp17Lockable types [thread.req.lockable]

33.2.5.1 In general [thread.req.lockable.general]

An execution agent is an entity such as a thread that may perform work in parallel with other execution agents.
[Note 1: 
Implementations or users can introduce other kinds of agents such as processes or thread-pool tasks.
— end note]
The calling agent is determined by context, e.g., the calling thread that contains the call, and so on.
[Note 2: 
Some lockable objects are “agent oblivious” in that they work for any execution agent model because they do not determine or store the agent's ID (e.g., an ordinary spin lock).
— end note]
The standard library templates unique_lock ([thread.lock.unique]), shared_lock ([thread.lock.shared]), scoped_lock ([thread.lock.scoped]), lock_guard ([thread.lock.guard]), lock, try_lock ([thread.lock.algorithm]), and condition_variable_any ([thread.condition.condvarany]) all operate on user-supplied lockable objects.
The Cpp17BasicLockable requirements, the Cpp17Lockable requirements, the Cpp17TimedLockable requirements, the Cpp17SharedLockable requirements, and the Cpp17SharedTimedLockable requirements list the requirements imposed by these library types in order to acquire or release ownership of a lock by a given execution agent.
[Note 3: 
The nature of any lock ownership and any synchronization it entails are not part of these requirements.
— end note]
A lock on an object m is said to be
  • a non-shared lock if it is acquired by a call to lock, try_lock, try_lock_for, or try_lock_until on m, or
  • a shared lock if it is acquired by a call to lock_shared, try_lock_shared, try_lock_shared_for, or try_lock_shared_until on m.
[Note 4: 
Only the method of lock acquisition is considered; the nature of any lock ownership is not part of these definitions.
— end note]

33.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]

A type L meets the Cpp17BasicLockable requirements if the following expressions are well-formed and have the specified semantics (m denotes a value of type L).
m.lock()
Effects: Blocks until a lock can be acquired for the current execution agent.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
m.unlock()
Preconditions: The current execution agent holds a non-shared lock on m.
Effects: Releases a non-shared lock on m held by the current execution agent.
Throws: Nothing.

33.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]

A type L meets the Cpp17Lockable requirements if it meets the Cpp17BasicLockable requirements and the following expressions are well-formed and have the specified semantics (m denotes a value of type L).
m.try_lock()
Effects: Attempts to acquire a lock for the current execution agent without blocking.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
Return type: bool.
Returns: true if the lock was acquired, otherwise false.

33.2.5.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]

A type L meets the Cpp17TimedLockable requirements if it meets the Cpp17Lockable requirements and the following expressions are well-formed and have the specified semantics (m denotes a value of type L, rel_time denotes a value of an instantiation of duration, and abs_time denotes a value of an instantiation of time_point).
m.try_lock_for(rel_time)
Effects: Attempts to acquire a lock for the current execution agent within the relative timeout ([thread.req.timing]) specified by rel_time.
The function will not return within the timeout specified by rel_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Return type: bool.
Returns: true if the lock was acquired, otherwise false.
m.try_lock_until(abs_time)
Effects: Attempts to acquire a lock for the current execution agent before the absolute timeout ([thread.req.timing]) specified by abs_time.
The function will not return before the timeout specified by abs_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Return type: bool.
Returns: true if the lock was acquired, otherwise false.

33.2.5.5 Cpp17SharedLockable requirements [thread.req.lockable.shared]

A type L meets the Cpp17SharedLockable requirements if the following expressions are well-formed, have the specified semantics, and the expression m.try_lock_shared() has type bool (m denotes a value of type L):
m.lock_shared()
Effects: Blocks until a lock can be acquired for the current execution agent.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
m.try_lock_shared()
Effects: Attempts to acquire a lock for the current execution agent without blocking.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
Returns: true if the lock was acquired, false otherwise.
m.unlock_shared()
Preconditions: The current execution agent holds a shared lock on m.
Effects: Releases a shared lock on m held by the current execution agent.
Throws: Nothing.

33.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]

A type L meets the Cpp17SharedTimedLockable requirements if it meets the Cpp17SharedLockable requirements, and the following expressions are well-formed, have type bool, and have the specified semantics (m denotes a value of type L, rel_time denotes a value of a specialization of chrono​::​duration, and abs_time denotes a value of a specialization of chrono​::​time_point).
m.try_lock_shared_for(rel_time)
Effects: Attempts to acquire a lock for the current execution agent within the relative timeout ([thread.req.timing]) specified by rel_time.
The function will not return within the timeout specified by rel_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Returns: true if the lock was acquired, false otherwise.
m.try_lock_shared_until(abs_time)
Effects: Attempts to acquire a lock for the current execution agent before the absolute timeout ([thread.req.timing]) specified by abs_time.
The function will not return before the timeout specified by abs_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Returns: true if the lock was acquired, false otherwise.