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

14 KiB
Raw Permalink Blame History

[futures.task]

32 Concurrency support library [thread]

32.10 Futures [futures]

32.10.10 Class template packaged_task [futures.task]

32.10.10.1 General [futures.task.general]

1

#

The class template packaged_task defines a type for wrapping a function or callable object so that the return value of the function or callable object is stored in a future when it is invoked.

2

#

When the packaged_task object is invoked, its stored task is invoked and the result (whether normal or exceptional) stored in the shared state.

Any futures that share the shared state will then be able to access the stored result.

🔗

namespace std {template class packaged_task; // not definedtemplate<class R, class... ArgTypes>class packaged_task<R(ArgTypes...)> {public:// construction and destruction packaged_task() noexcept; templateexplicit packaged_task(F&& f); template<class F, class Allocator>explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f); ~packaged_task(); // no copy packaged_task(const packaged_task&) = delete; packaged_task& operator=(const packaged_task&) = delete; // move support packaged_task(packaged_task&& rhs) noexcept; packaged_task& operator=(packaged_task&& rhs) noexcept; void swap(packaged_task& other) noexcept; bool valid() const noexcept; // result retrieval future get_future(); // executionvoid operator()(ArgTypes... ); void make_ready_at_thread_exit(ArgTypes...); void reset(); }; template<class R, class... ArgTypes> packaged_task(R (*)(ArgTypes...)) -> packaged_task<R(ArgTypes...)>; template packaged_task(F) -> packaged_task<see below>;}

32.10.10.2 Member functions [futures.task.members]

🔗

packaged_task() noexcept;

1

#

Effects: The object has no shared state and no stored task.

🔗

template<class F> explicit packaged_task(F&& f);

2

#

Effects: Equivalent topackaged_task(allocator_arg, allocator(), std::forward(f)).

🔗

template<class F, class Allocator> explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);

3

#

Constraints: remove_cvref_t is not the same type as packaged_task<R(ArgTypes...)>.

4

#

Mandates: is_invocable_r_v<R, decay_t&, ArgTypes...> is true.

5

#

Preconditions: Allocator meets the Cpp17Allocator requirements ([allocator.requirements.general]).

6

#

Effects: Let A2 beallocator_traits::rebind_alloc<unspecified> and let a2 be an object of type A2 initialized withA2(a).

Constructs a new packaged_task object with a stored task of type decay_t and a shared state.

Initializes the object's stored task with std::forward(f).

Uses a2 to allocate storage for the shared state and stores a copy of a2 in the shared state.

7

#

Throws: Any exceptions thrown by the initialization of the stored task.

If storage for the shared state cannot be allocated, any exception thrown byA2::allocate.

🔗

template<class F> packaged_task(F) -> packaged_task<see below>;

8

#

Constraints: &F::operator() is well-formed when treated as an unevaluated operand ([expr.context]) and either

F::operator() is a non-static member function anddecltype(&F::operator()) is either of the formR(G::*)(A...) cv &opt noexceptopt or of the formR(*)(G, A...) noexceptopt for a type G, or

F::operator() is a static member function anddecltype(&F::operator()) is of the formR(*)(A...) noexceptopt.

9

#

Remarks: The deduced type is packaged_task<R(A...)>.

🔗

packaged_task(packaged_task&& rhs) noexcept;

10

#

Effects: Transfers ownership ofrhs's shared state to *this, leaving rhs with no shared state.

Moves the stored task from rhs to *this.

11

#

Postconditions: rhs has no shared state.

🔗

packaged_task& operator=(packaged_task&& rhs) noexcept;

12

#

Effects:

Releases any shared state ([futures.state]);

calls packaged_task(std::move(rhs)).swap(*this).

🔗

~packaged_task();

13

#

Effects: Abandons any shared state ([futures.state]).

🔗

void swap(packaged_task& other) noexcept;

14

#

Effects: Exchanges the shared states and stored tasks of *this and other.

15

#

Postconditions: *this has the same shared state and stored task (if any) as other prior to the call to swap.

other has the same shared state and stored task (if any) as *this prior to the call to swap.

🔗

bool valid() const noexcept;

16

#

Returns: true only if *this has a shared state.

🔗

future<R> get_future();

17

#

Synchronization: Calls to this function do not introduce data races ([intro.multithread]) with calls tooperator() ormake_ready_at_thread_exit.

[Note 1:

Such calls need not synchronize with each other.

— end note]

18

#

Returns: A future object that shares the same shared state as *this.

19

#

Throws: A future_error object if an error occurs.

20

#

Error conditions:

  • (20.1)

    future_already_retrieved if get_future has already been called on a packaged_task object with the same shared state as *this.

  • (20.2)

    no_state if *this has no shared state.

🔗

void operator()(ArgTypes... args);

21

#

Effects: As if by INVOKE(f, t1, t2, …, tN) ([func.require]), where f is the stored task of *this andt1, t2, …, tN are the values in args....

If the task returns normally, the return value is stored as the asynchronous result in the shared state of*this, otherwise the exception thrown by the task is stored.

The shared state of *this is made ready, and any threads blocked in a function waiting for the shared state of *this to become ready are unblocked.

22

#

Throws: A future_error exception object if there is no shared state or the stored task has already been invoked.

23

#

Error conditions:

  • (23.1)

    promise_already_satisfied if the stored task has already been invoked.

  • (23.2)

    no_state if *this has no shared state.

🔗

void make_ready_at_thread_exit(ArgTypes... args);

24

#

Effects: As if by INVOKE(f, t1, t2, …, tN) ([func.require]), where f is the stored task andt1, t2, …, tN are the values in args....

If the task returns normally, the return value is stored as the asynchronous result in the shared state of*this, otherwise the exception thrown by the task is stored.

In either case, this is done without making that state ready ([futures.state]) immediately.

Schedules the shared state to be made ready when the current thread exits, after all objects with thread storage duration associated with the current thread have been destroyed.

25

#

Throws: future_error if an error condition occurs.

26

#

Error conditions:

  • (26.1)

    promise_already_satisfied if the stored task has already been invoked.

  • (26.2)

    no_state if *this has no shared state.

🔗

void reset();

27

#

Effects: Equivalent to:if (!valid()) {throw future_error(future_errc::no_state);}this = packaged_task(allocator_arg, a, std::move(f)); wheref is the task stored inthis and a is the allocator stored in the shared state.

[Note 2:

This constructs a new shared state for *this.

The old state is abandoned ([futures.state]).

— end note]

28

#

Throws:

  • (28.1)

    Any exception thrown by the packaged_task constructor.

  • (28.2)

    future_error with an error condition of no_state if *this has no shared state.

32.10.10.3 Globals [futures.task.nonmembers]

🔗

template<class R, class... ArgTypes> void swap(packaged_task<R(ArgTypes...)>& x, packaged_task<R(ArgTypes...)>& y) noexcept;

1

#

Effects: As if by x.swap(y).