[thread.req.lockable]

# 32 Concurrency support library [[thread]](./#thread)

## 32.2 Requirements [[thread.req]](thread.req#lockable)

### 32.2.5 Requirements for *Cpp17Lockable* types [thread.req.lockable]

#### [32.2.5.1](#general) General [[thread.req.lockable.general]](thread.req.lockable.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L174)

An [*execution agent*](#def:execution_agent "32.2.5.1 General [thread.req.lockable.general]") is an entity such as a thread that may perform work in parallel with
other execution agents[.](#general-1.sentence-1)

[*Note [1](#general-note-1)*:

Implementations or users can introduce other kinds of
agents such as processes or thread-pool tasks[.](#general-1.sentence-2)

â *end note*]

The calling agent is determined by
context, e.g., the calling thread that contains the call, and so on[.](#general-1.sentence-3)

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L184)

[*Note [2](#general-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)[.](#general-2.sentence-1)

â *end note*]

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L191)

The standard library templates unique_lock ([[thread.lock.unique]](thread.lock.unique "32.6.5.4 Class template unique_­lock")),shared_lock ([[thread.lock.shared]](thread.lock.shared "32.6.5.5 Class template shared_­lock")),scoped_lock ([[thread.lock.scoped]](thread.lock.scoped "32.6.5.3 Class template scoped_­lock")),lock_guard ([[thread.lock.guard]](thread.lock.guard "32.6.5.2 Class template lock_­guard")), lock,try_lock ([[thread.lock.algorithm]](thread.lock.algorithm "32.6.6 Generic locking algorithms")), andcondition_variable_any ([[thread.condition.condvarany]](thread.condition.condvarany "32.7.5 Class condition_­variable_­any")) all operate on user-supplied
lockable objects[.](#general-3.sentence-1)

The [*Cpp17BasicLockable*](#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements, the [*Cpp17Lockable*](#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements,
the [*Cpp17TimedLockable*](#:Cpp17TimedLockable "32.2.5.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]") requirements,
the [*Cpp17SharedLockable*](#:Cpp17SharedLockable "32.2.5.5 Cpp17SharedLockable requirements [thread.req.lockable.shared]") requirements, and
the [*Cpp17SharedTimedLockable*](#:Cpp17SharedTimedLockable "32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]") requirements
list the requirements imposed by these library types
in order to acquire or release ownership of a lock by a given execution agent[.](#general-3.sentence-2)

[*Note [3](#general-note-3)*:

The nature of any lock ownership and any synchronization it entails are not part
of these requirements[.](#general-3.sentence-3)

â *end note*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L209)

A lock on an object m is said to be

- [(4.1)](#general-4.1)

a [*non-shared lock*](#def:lock,non-shared "32.2.5.1 General [thread.req.lockable.general]") if it is acquired by a call tolock,try_lock,try_lock_for, ortry_lock_until on m, or

- [(4.2)](#general-4.2)

a [*shared lock*](#def:lock,shared "32.2.5.1 General [thread.req.lockable.general]") if it is acquired by a call tolock_shared,try_lock_shared,try_lock_shared_for, ortry_lock_shared_until on m[.](#general-4.sentence-1)

[*Note [4](#general-note-4)*:

Only the method of lock acquisition is considered;
the nature of any lock ownership is not part of these definitions[.](#general-4.sentence-2)

â *end note*]

#### [32.2.5.2](#basic) *Cpp17BasicLockable* requirements [[thread.req.lockable.basic]](thread.req.lockable.basic)

[1](#basic-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L232)

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)[.](#basic-1.sentence-1)

[ð](#basic-itemdecl:1)

`m.lock()
`

[2](#basic-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L241)

*Effects*: Blocks until a lock can be acquired for the current execution agent[.](#basic-2.sentence-1)

If an exception
is thrown then a lock shall not have been acquired for the current execution agent[.](#basic-2.sentence-2)

[ð](#basic-itemdecl:2)

`m.unlock()
`

[3](#basic-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L253)

*Preconditions*: The current execution agent holds a non-shared lock on m[.](#basic-3.sentence-1)

[4](#basic-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L257)

*Effects*: Releases a non-shared lock on m held by the current execution agent[.](#basic-4.sentence-1)

[5](#basic-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L261)

*Throws*: Nothing[.](#basic-5.sentence-1)

#### [32.2.5.3](#req) *Cpp17Lockable* requirements [[thread.req.lockable.req]](thread.req.lockable.req)

[1](#req-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L268)

A type L meets the *Cpp17Lockable* requirements if it meets the [*Cpp17BasicLockable*](#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements and the following expressions are well-formed and have the specified semantics
(m denotes a value of type L)[.](#req-1.sentence-1)

[ð](#req-itemdecl:1)

`m.try_lock()
`

[2](#req-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L278)

*Effects*: Attempts to acquire a lock for the current execution agent without blocking[.](#req-2.sentence-1)

If an
exception is thrown then a lock shall not have been acquired for the current execution agent[.](#req-2.sentence-2)

[3](#req-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L283)

*Return type*: bool[.](#req-3.sentence-1)

[4](#req-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L286)

*Returns*: true if the lock was acquired, otherwise false[.](#req-4.sentence-1)

#### [32.2.5.4](#timed) *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]](thread.req.lockable.timed)

[1](#timed-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L293)

A type L meets the *Cpp17TimedLockable* requirements if it meets the [*Cpp17Lockable*](#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") 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](time.duration "30.5 Class template duration [time.duration]"), and abs_time denotes a value
of an instantiation of [time_point](time.point "30.6 Class template time_­point [time.point]"))[.](#timed-1.sentence-1)

[ð](#timed-itemdecl:1)

`m.try_lock_for(rel_time)
`

[2](#timed-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L305)

*Effects*: Attempts to acquire a lock for the current execution agent within the relative
timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by rel_time[.](#timed-2.sentence-1)

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[.](#timed-2.sentence-2)

If an exception is thrown then a lock has not been
acquired for the current execution agent[.](#timed-2.sentence-3)

[3](#timed-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L313)

*Return type*: bool[.](#timed-3.sentence-1)

[4](#timed-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L316)

*Returns*: true if the lock was acquired, otherwise false[.](#timed-4.sentence-1)

[ð](#timed-itemdecl:2)

`m.try_lock_until(abs_time)
`

[5](#timed-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L326)

*Effects*: Attempts to acquire a lock for the current execution agent before the absolute
timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by abs_time[.](#timed-5.sentence-1)

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[.](#timed-5.sentence-2)

If an exception is thrown then a lock has not been acquired
for the current execution agent[.](#timed-5.sentence-3)

[6](#timed-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L334)

*Return type*: bool[.](#timed-6.sentence-1)

[7](#timed-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L337)

*Returns*: true if the lock was acquired, otherwise false[.](#timed-7.sentence-1)

#### [32.2.5.5](#shared) *Cpp17SharedLockable* requirements [[thread.req.lockable.shared]](thread.req.lockable.shared)

[1](#shared-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L344)

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):

[ð](#shared-itemdecl:1)

`m.lock_shared()
`

[2](#shared-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L355)

*Effects*: Blocks until a lock can be acquired for the current execution agent[.](#shared-2.sentence-1)

If an exception is thrown then a lock shall not have been acquired for
the current execution agent[.](#shared-2.sentence-2)

[ð](#shared-itemdecl:2)

`m.try_lock_shared()
`

[3](#shared-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L367)

*Effects*: Attempts to acquire a lock for the current execution agent without blocking[.](#shared-3.sentence-1)

If an exception is thrown then a lock shall not have been acquired for
the current execution agent[.](#shared-3.sentence-2)

[4](#shared-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L373)

*Returns*: true if the lock was acquired, false otherwise[.](#shared-4.sentence-1)

[ð](#shared-itemdecl:3)

`m.unlock_shared()
`

[5](#shared-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L383)

*Preconditions*: The current execution agent holds a shared lock on m[.](#shared-5.sentence-1)

[6](#shared-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L387)

*Effects*: Releases a shared lock on m held by the current execution agent[.](#shared-6.sentence-1)

[7](#shared-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L391)

*Throws*: Nothing[.](#shared-7.sentence-1)

#### [32.2.5.6](#shared.timed) *Cpp17SharedTimedLockable* requirements [[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed)

[1](#shared.timed-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L398)

A type L meets the *Cpp17SharedTimedLockable* requirements if
it meets the [*Cpp17SharedLockable*](#:Cpp17SharedLockable "32.2.5.5 Cpp17SharedLockable requirements [thread.req.lockable.shared]") 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, andabs_time denotes a value of a specialization of chrono​::​time_point)[.](#shared.timed-1.sentence-1)

[ð](#shared.timed-itemdecl:1)

`m.try_lock_shared_for(rel_time)
`

[2](#shared.timed-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L412)

*Effects*: Attempts to acquire a lock for the current execution agent within
the relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by rel_time[.](#shared.timed-2.sentence-1)

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[.](#shared.timed-2.sentence-2)

If an exception is thrown then a lock has not been acquired for
the current execution agent[.](#shared.timed-2.sentence-3)

[3](#shared.timed-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L421)

*Returns*: true if the lock was acquired, false otherwise[.](#shared.timed-3.sentence-1)

[ð](#shared.timed-itemdecl:2)

`m.try_lock_shared_until(abs_time)
`

[4](#shared.timed-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L431)

*Effects*: Attempts to acquire a lock for the current execution agent before
the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by abs_time[.](#shared.timed-4.sentence-1)

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[.](#shared.timed-4.sentence-2)

If an exception is thrown then a lock has not been acquired for
the current execution agent[.](#shared.timed-4.sentence-3)

[5](#shared.timed-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L440)

*Returns*: true if the lock was acquired, false otherwise[.](#shared.timed-5.sentence-1)
