Files
2025-10-25 03:02:53 +03:00

577 lines
25 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[thread.req]
# 32 Concurrency support library [[thread]](./#thread)
## 32.2 Requirements [thread.req]
### [32.2.1](#paramname) Template parameter names [[thread.req.paramname]](thread.req.paramname)
[1](#paramname-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L31)
Throughout this Clause, the names of template parameters are used to express type
requirements[.](#paramname-1.sentence-1)
Predicate is a function object type ([[function.objects]](function.objects "22.10Function objects"))[.](#paramname-1.sentence-2)
Let pred denote an lvalue of type Predicate[.](#paramname-1.sentence-3)
Then the expression pred() shall be well-formed and
the type decltype(pred()) shall model[*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2Boolean testability[concept.booleantestable]") ([[concept.booleantestable]](concept.booleantestable "18.5.2Boolean testability"))[.](#paramname-1.sentence-4)
The return value of pred(), converted to bool,
yields true if the corresponding test condition is satisfied, andfalse otherwise[.](#paramname-1.sentence-5)
If a template parameter is named Clock,
the corresponding template argument shall be a type C that meets the [*Cpp17Clock*](time.clock.req#:Cpp17Clock "30.3Cpp17Clock requirements[time.clock.req]") requirements ([[time.clock.req]](time.clock.req "30.3Cpp17Clock requirements"));
the program is ill-formed if is_clock_v<C> is false[.](#paramname-1.sentence-6)
### [32.2.2](#exception) Exceptions [[thread.req.exception]](thread.req.exception)
[1](#exception-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L49)
Some functions described in this Clause are specified to throw exceptions of typesystem_error ([[syserr.syserr]](syserr.syserr "19.5.8Class system_­error"))[.](#exception-1.sentence-1)
Such exceptions are thrown if
any of the function's error conditions is detected or
a call to
an operating system or other underlying API results in an error that prevents the
library function from
meeting its specifications[.](#exception-1.sentence-2)
Failure to allocate storage is reported as described
in [[res.on.exception.handling]](res.on.exception.handling "16.4.6.14Restrictions on exception handling")[.](#exception-1.sentence-3)
[*Example [1](#exception-example-1)*:
Consider a function in this Clause that is specified to throw exceptions of typesystem_error and specifies error conditions that includeoperation_not_permitted for a thread that does not have the privilege to
perform the operation[.](#exception-1.sentence-4)
Assume that, during the execution of this function, an errno of EPERM is reported by a POSIX API call used by the implementation[.](#exception-1.sentence-5)
Since POSIX
specifies an errno of EPERM when “the caller does not have the privilege
to perform the operation”, the implementation maps EPERM to anerror_condition of operation_not_permitted ([[syserr]](syserr "19.5System error support")) and an exception
of type system_error is thrown[.](#exception-1.sentence-6)
— *end example*]
[2](#exception-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L71)
The error_code reported by such an exception's code() member function
compares equal to one of the conditions specified in the function's error condition
element[.](#exception-2.sentence-1)
### [32.2.3](#native) Native handles [[thread.req.native]](thread.req.native)
[1](#native-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L78)
Several classes described in this Clause have members native_handle_type andnative_handle[.](#native-1.sentence-1)
The presence of these members and their semantics isimplementation-defined[.](#native-1.sentence-2)
[*Note [1](#native-note-1)*:
These members allow implementations to provide access
to implementation details[.](#native-1.sentence-3)
Their names are specified to facilitate portable compile-time
detection[.](#native-1.sentence-4)
Actual use of these members is inherently non-portable[.](#native-1.sentence-5)
— *end note*]
### [32.2.4](#timing) Timing specifications [[thread.req.timing]](thread.req.timing)
[1](#timing-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L90)
Several functions described in this Clause take an argument to specify a timeout[.](#timing-1.sentence-1)
These
timeouts are specified as either a duration or a time_point type as
specified in [[time]](time "30Time library")[.](#timing-1.sentence-2)
[2](#timing-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L95)
Implementations necessarily have some delay in returning from a timeout[.](#timing-2.sentence-1)
Any overhead in
interrupt response, function return, and scheduling induces a “quality of implementation”
delay, expressed as duration Di[.](#timing-2.sentence-2)
Ideally, this delay would be zero[.](#timing-2.sentence-3)
Further, any contention for
processor and memory resources induces a “quality of management” delay, expressed as durationDm[.](#timing-2.sentence-4)
The delay durations may vary from timeout to timeout, but in all cases shorter is better[.](#timing-2.sentence-5)
[3](#timing-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L102)
The functions whose names end in _for take an argument that
specifies a duration[.](#timing-3.sentence-1)
These functions produce relative timeouts[.](#timing-3.sentence-2)
Implementations
should use a steady clock to measure time for these functions[.](#timing-3.sentence-3)[293](#footnote-293 "Implementations for which standard time units are meaningful will typically have a steady clock within their hardware implementation.")
Given a duration
argument Dt, the real-time duration of the timeout is Dt+Di+Dm[.](#timing-3.sentence-4)
[4](#timing-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L113)
The functions whose names end in _until take an argument that specifies a time
point[.](#timing-4.sentence-1)
These functions produce absolute timeouts[.](#timing-4.sentence-2)
Implementations should use the clock
specified in the time point to measure time for these functions[.](#timing-4.sentence-3)
Given a clock time point
argument Ct, the clock time point of the return from timeout should be Ct+Di+Dm when the clock is not adjusted during the timeout[.](#timing-4.sentence-4)
If the clock is adjusted to the time Ca during the timeout, the behavior should be as follows:
- [(4.1)](#timing-4.1)
If Ca>Ct, the waiting function should wake as soon as possible, i.e., Ca+Di+Dm,
since the timeout is already satisfied[.](#timing-4.1.sentence-1)
This specification may result in the total
duration of the wait decreasing when measured against a steady clock[.](#timing-4.1.sentence-2)
- [(4.2)](#timing-4.2)
If Ca≤Ct, the waiting function should not time out until Clock::now() returns a
time Cn≥Ct, i.e., waking at Ct+Di+Dm[.](#timing-4.2.sentence-1)
[*Note [1](#timing-note-1)*:
When the clock is adjusted
backwards, this specification can result in the total duration of the wait increasing when
measured against a steady clock[.](#timing-4.2.sentence-2)
When the clock is adjusted forwards, this specification can
result in the total duration of the wait decreasing when measured against a steady clock[.](#timing-4.2.sentence-3)
— *end note*]
An implementation returns from such a timeout at any point from the time specified above to
the time it would return from a steady-clock relative timeout on the difference between Ct and the time point of the call to the _until function[.](#timing-4.sentence-6)
*Recommended practice*: Implementations
should decrease the duration of the wait when the clock is adjusted forwards[.](#timing-4.sentence-7)
[5](#timing-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L146)
[*Note [2](#timing-note-2)*:
If the clock is not synchronized with a steady clock, e.g., a CPU time clock, these
timeouts can fail to provide useful functionality[.](#timing-5.sentence-1)
— *end note*]
[6](#timing-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L152)
The resolution of timing provided by an implementation depends on both operating system
and hardware[.](#timing-6.sentence-1)
The finest resolution provided by an implementation is called the[*native resolution*](#def:native_resolution)[.](#timing-6.sentence-2)
[7](#timing-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L157)
Implementation-provided clocks that are used for these functions meet the[*Cpp17TrivialClock*](time.clock.req#:Cpp17TrivialClock "30.3Cpp17Clock requirements[time.clock.req]") requirements ([[time.clock.req]](time.clock.req "30.3Cpp17Clock requirements"))[.](#timing-7.sentence-1)
[8](#timing-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L161)
A function that takes an argument which specifies a timeout will throw if,
during its execution, a clock, time point, or time duration throws an exception[.](#timing-8.sentence-1)
Such exceptions are referred to as [*timeout-related exceptions*](#def:timeout-related_exceptions)[.](#timing-8.sentence-2)
[*Note [3](#timing-note-3)*:
Instantiations of clock, time point and duration types supplied by
the implementation as specified in [[time.clock]](time.clock "30.7Clocks") do not throw exceptions[.](#timing-8.sentence-3)
— *end note*]
[293)](#footnote-293)[293)](#footnoteref-293)
Implementations for which standard time units are meaningful will typically
have a steady clock within their hardware implementation[.](#footnote-293.sentence-1)
### [32.2.5](#lockable) Requirements for *Cpp17Lockable* types [[thread.req.lockable]](thread.req.lockable)
#### [32.2.5.1](#lockable.general) General [[thread.req.lockable.general]](thread.req.lockable.general)
[1](#lockable.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L174)
An [*execution agent*](#def:execution_agent "32.2.5.1General[thread.req.lockable.general]") is an entity such as a thread that may perform work in parallel with
other execution agents[.](#lockable.general-1.sentence-1)
[*Note [1](#lockable.general-note-1)*:
Implementations or users can introduce other kinds of
agents such as processes or thread-pool tasks[.](#lockable.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[.](#lockable.general-1.sentence-3)
[2](#lockable.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L184)
[*Note [2](#lockable.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)[.](#lockable.general-2.sentence-1)
— *end note*]
[3](#lockable.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.4Class template unique_­lock")),shared_lock ([[thread.lock.shared]](thread.lock.shared "32.6.5.5Class template shared_­lock")),scoped_lock ([[thread.lock.scoped]](thread.lock.scoped "32.6.5.3Class template scoped_­lock")),lock_guard ([[thread.lock.guard]](thread.lock.guard "32.6.5.2Class template lock_­guard")), lock,try_lock ([[thread.lock.algorithm]](thread.lock.algorithm "32.6.6Generic locking algorithms")), andcondition_variable_any ([[thread.condition.condvarany]](thread.condition.condvarany "32.7.5Class condition_­variable_­any")) all operate on user-supplied
lockable objects[.](#lockable.general-3.sentence-1)
The [*Cpp17BasicLockable*](#:Cpp17BasicLockable "32.2.5.2Cpp17BasicLockable requirements[thread.req.lockable.basic]") requirements, the [*Cpp17Lockable*](#:Cpp17Lockable "32.2.5.3Cpp17Lockable requirements[thread.req.lockable.req]") requirements,
the [*Cpp17TimedLockable*](#:Cpp17TimedLockable "32.2.5.4Cpp17TimedLockable requirements[thread.req.lockable.timed]") requirements,
the [*Cpp17SharedLockable*](#:Cpp17SharedLockable "32.2.5.5Cpp17SharedLockable requirements[thread.req.lockable.shared]") requirements, and
the [*Cpp17SharedTimedLockable*](#:Cpp17SharedTimedLockable "32.2.5.6Cpp17SharedTimedLockable 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[.](#lockable.general-3.sentence-2)
[*Note [3](#lockable.general-note-3)*:
The nature of any lock ownership and any synchronization it entails are not part
of these requirements[.](#lockable.general-3.sentence-3)
— *end note*]
[4](#lockable.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)](#lockable.general-4.1)
a [*non-shared lock*](#def:lock,non-shared "32.2.5.1General[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)](#lockable.general-4.2)
a [*shared lock*](#def:lock,shared "32.2.5.1General[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[.](#lockable.general-4.sentence-1)
[*Note [4](#lockable.general-note-4)*:
Only the method of lock acquisition is considered;
the nature of any lock ownership is not part of these definitions[.](#lockable.general-4.sentence-2)
— *end note*]
#### [32.2.5.2](#lockable.basic) *Cpp17BasicLockable* requirements [[thread.req.lockable.basic]](thread.req.lockable.basic)
[1](#lockable.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)[.](#lockable.basic-1.sentence-1)
[🔗](#lockable.basic-itemdecl:1)
`m.lock()
`
[2](#lockable.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[.](#lockable.basic-2.sentence-1)
If an exception
is thrown then a lock shall not have been acquired for the current execution agent[.](#lockable.basic-2.sentence-2)
[🔗](#lockable.basic-itemdecl:2)
`m.unlock()
`
[3](#lockable.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[.](#lockable.basic-3.sentence-1)
[4](#lockable.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[.](#lockable.basic-4.sentence-1)
[5](#lockable.basic-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L261)
*Throws*: Nothing[.](#lockable.basic-5.sentence-1)
#### [32.2.5.3](#lockable.req) *Cpp17Lockable* requirements [[thread.req.lockable.req]](thread.req.lockable.req)
[1](#lockable.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.2Cpp17BasicLockable 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)[.](#lockable.req-1.sentence-1)
[🔗](#lockable.req-itemdecl:1)
`m.try_lock()
`
[2](#lockable.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[.](#lockable.req-2.sentence-1)
If an
exception is thrown then a lock shall not have been acquired for the current execution agent[.](#lockable.req-2.sentence-2)
[3](#lockable.req-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L283)
*Return type*: bool[.](#lockable.req-3.sentence-1)
[4](#lockable.req-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L286)
*Returns*: true if the lock was acquired, otherwise false[.](#lockable.req-4.sentence-1)
#### [32.2.5.4](#lockable.timed) *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]](thread.req.lockable.timed)
[1](#lockable.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.3Cpp17Lockable 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.5Class template duration[time.duration]"), and abs_time denotes a value
of an instantiation of [time_point](time.point "30.6Class template time_­point[time.point]"))[.](#lockable.timed-1.sentence-1)
[🔗](#lockable.timed-itemdecl:1)
`m.try_lock_for(rel_time)
`
[2](#lockable.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]](#timing "32.2.4Timing specifications")) specified by rel_time[.](#lockable.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[.](#lockable.timed-2.sentence-2)
If an exception is thrown then a lock has not been
acquired for the current execution agent[.](#lockable.timed-2.sentence-3)
[3](#lockable.timed-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L313)
*Return type*: bool[.](#lockable.timed-3.sentence-1)
[4](#lockable.timed-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L316)
*Returns*: true if the lock was acquired, otherwise false[.](#lockable.timed-4.sentence-1)
[🔗](#lockable.timed-itemdecl:2)
`m.try_lock_until(abs_time)
`
[5](#lockable.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]](#timing "32.2.4Timing specifications")) specified by abs_time[.](#lockable.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[.](#lockable.timed-5.sentence-2)
If an exception is thrown then a lock has not been acquired
for the current execution agent[.](#lockable.timed-5.sentence-3)
[6](#lockable.timed-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L334)
*Return type*: bool[.](#lockable.timed-6.sentence-1)
[7](#lockable.timed-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L337)
*Returns*: true if the lock was acquired, otherwise false[.](#lockable.timed-7.sentence-1)
#### [32.2.5.5](#lockable.shared) *Cpp17SharedLockable* requirements [[thread.req.lockable.shared]](thread.req.lockable.shared)
[1](#lockable.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):
[🔗](#lockable.shared-itemdecl:1)
`m.lock_shared()
`
[2](#lockable.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[.](#lockable.shared-2.sentence-1)
If an exception is thrown then a lock shall not have been acquired for
the current execution agent[.](#lockable.shared-2.sentence-2)
[🔗](#lockable.shared-itemdecl:2)
`m.try_lock_shared()
`
[3](#lockable.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[.](#lockable.shared-3.sentence-1)
If an exception is thrown then a lock shall not have been acquired for
the current execution agent[.](#lockable.shared-3.sentence-2)
[4](#lockable.shared-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L373)
*Returns*: true if the lock was acquired, false otherwise[.](#lockable.shared-4.sentence-1)
[🔗](#lockable.shared-itemdecl:3)
`m.unlock_shared()
`
[5](#lockable.shared-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L383)
*Preconditions*: The current execution agent holds a shared lock on m[.](#lockable.shared-5.sentence-1)
[6](#lockable.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[.](#lockable.shared-6.sentence-1)
[7](#lockable.shared-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L391)
*Throws*: Nothing[.](#lockable.shared-7.sentence-1)
#### [32.2.5.6](#lockable.shared.timed) *Cpp17SharedTimedLockable* requirements [[thread.req.lockable.shared.timed]](thread.req.lockable.shared.timed)
[1](#lockable.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.5Cpp17SharedLockable 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)[.](#lockable.shared.timed-1.sentence-1)
[🔗](#lockable.shared.timed-itemdecl:1)
`m.try_lock_shared_for(rel_time)
`
[2](#lockable.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]](#timing "32.2.4Timing specifications")) specified by rel_time[.](#lockable.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[.](#lockable.shared.timed-2.sentence-2)
If an exception is thrown then a lock has not been acquired for
the current execution agent[.](#lockable.shared.timed-2.sentence-3)
[3](#lockable.shared.timed-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L421)
*Returns*: true if the lock was acquired, false otherwise[.](#lockable.shared.timed-3.sentence-1)
[🔗](#lockable.shared.timed-itemdecl:2)
`m.try_lock_shared_until(abs_time)
`
[4](#lockable.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]](#timing "32.2.4Timing specifications")) specified by abs_time[.](#lockable.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[.](#lockable.shared.timed-4.sentence-2)
If an exception is thrown then a lock has not been acquired for
the current execution agent[.](#lockable.shared.timed-4.sentence-3)
[5](#lockable.shared.timed-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L440)
*Returns*: true if the lock was acquired, false otherwise[.](#lockable.shared.timed-5.sentence-1)