deal.II version GIT relicensing-2287-g6548a49e0a 2024-12-20 18:30:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Private Attributes | List of all members

#include <deal.II/base/thread_management.h>

Inheritance diagram for Threads::Task< RT >:
Inheritance graph
[legend]

Classes

class  TaskData
 

Public Member Functions

 Task (const std::function< RT()> &function_object)
 
 Task ()=default
 
 Task (const Task &other)=default
 
 Task (Task &&other) noexcept=default
 
Taskoperator= (const Task &other)=default
 
Taskoperator= (Task &&other) noexcept=default
 
void join () const
 
bool joinable () const
 
internal::return_value< RT >::reference_type return_value ()
 

Static Public Member Functions

static ::ExceptionBaseExcNoTask ()
 

Private Attributes

std::shared_ptr< TaskDatatask_data
 

Detailed Description

template<typename RT = void>
class Threads::Task< RT >

This class describes a task object, i.e., what one obtains by calling Threads::new_task(). The idea is that Threads::new_task() allows one to run a function whenever the C++ run-time system finds it convenient – typically, when there is an idle processor available. This can be used to run things in the background when there is no immediate need for the result, or if there are other things that could well be done in parallel. Whenever the result of that background task is needed, one can call either Threads::Task::join() to just wait for the task to finish, or Threads::Task::return_value() to obtain the value that was returned by the function that was run on that background task. In both of these cases, one continues to reference the operation (namely, the Task object) that was in charge of computing the returned value. An alternative is to use the Threads::TaskResult class that references the object being computed rather than the task that computes it.

This class is related to, but semantically not the same as, the std::future class that is returned by std::async (which is itself similar to what Threads::new_task() does). The principal conceptual difference is that std::future references the returned object (like Threads::TaskResult) whereas the current object references the task that computes that result.

Definition at line 488 of file thread_management.h.

Constructor & Destructor Documentation

◆ Task() [1/4]

template<typename RT = void>
Threads::Task< RT >::Task ( const std::function< RT()> &  function_object)
inline

Construct a task object, given a function object to execute on the task, and then schedule this function for execution. However, when MultithreadInfo::n_threads() returns 1, i.e., if the deal.II runtime system has been configured to only use one thread, then just execute the given function object.

Postcondition
Using this constructor automatically makes the task object joinable().

Definition at line 502 of file thread_management.h.

◆ Task() [2/4]

template<typename RT = void>
Threads::Task< RT >::Task ( )
default

Default constructor. You can't do much with a task object constructed this way, except for assigning it a task object that holds data created by the Threads::new_task() functions.

Postcondition
Using this constructor leaves the object in an unjoinable state, i.e., joinable() will return false.

◆ Task() [3/4]

template<typename RT = void>
Threads::Task< RT >::Task ( const Task< RT > &  other)
default

Copy constructor. At the end of this operation, both the original and the new object refer to the same task, and both can ask for the returned object. That is, if you do

Task< RT > new_task(const std::function< RT()> &function)

then calling t2.return_value() will return the same object (not just an object with the same value, but in fact the same address!) as calling t1.return_value().

◆ Task() [4/4]

template<typename RT = void>
Threads::Task< RT >::Task ( Task< RT > &&  other)
defaultnoexcept

Move constructor. At the end of this operation, the original object no longer refers to a task, and the new object refers to the same task as the original one originally did. That is, if you do

Threads::Task<T> t2 (std::move(t1));

then calling t2.return_value() will return the object computed by the task, and t1.return_value() will result in an error because t1 no longer refers to a task and consequently does not know anything about a return value.

Member Function Documentation

◆ operator=() [1/2]

template<typename RT = void>
Task & Threads::Task< RT >::operator= ( const Task< RT > &  other)
default

Copy operator. At the end of this operation, both the right hand and the left hand object refer to the same task, and both can ask for the returned object. That is, if you do

then calling t2.return_value() will return the same object (not just an object with the same value, but in fact the same address!) as calling t1.return_value().

◆ operator=() [2/2]

template<typename RT = void>
Task & Threads::Task< RT >::operator= ( Task< RT > &&  other)
defaultnoexcept

Move operator. At the end of this operation, the right hand side object no longer refers to a task, and the left hand side object refers to the same task as the right hand side one originally did. That is, if you do

t2 = std::move(t1);

then calling t2.return_value() will return the object computed by the task, and t1.return_value() will result in an error because t1 no longer refers to a task and consequently does not know anything about a return value.

◆ join()

template<typename RT = void>
void Threads::Task< RT >::join ( ) const
inline

Join the task represented by this object, i.e. wait for it to finish.

A task can be joined multiple times (while the first join() operation may block until the task has completed running, all successive attempts to join will return immediately).

If the operation that was executed on the task with which this object was initialized throws an exception instead of returning regularly, then calling the current join() function will first wait for that task to finish, and then in turn throw the exception that the task operation had thrown originally. This allows for the propagation of exceptions from tasks executed on a separate thread to the calling thread.

(This behavior differs from that of std::future, where the std::future::wait() function only waits for completion of the operation, whereas the exception is propagated only once one calls std::future::get(). However, this is awkward when putting void functions onto separate tasks because these do not actually return anything; consequently, it is more natural to call std::task::wait() for such tasks than the std::task::get() function since the latter does not, actually, return anything that could be gotten.)

Precondition
You can't call this function if you have used the default constructor of this class and have not assigned a task object to it. In other words, the function joinable() must return true.

Definition at line 738 of file thread_management.h.

◆ joinable()

template<typename RT = void>
bool Threads::Task< RT >::joinable ( ) const
inline

Return whether the current object can be joined. You can join a task object once a task (typically created with Threads::new_task()) has actually been assigned to it. On the other hand, the function returns false if the object has been default constructed.

A task can be joined multiple times (while the first join() operation may block until the task has completed running, all successive attempts to join will return immediately). Consequently, if this function returns true, it will continue to return true until the task object it reports on is assigned to from another object.

Definition at line 759 of file thread_management.h.

◆ return_value()

template<typename RT = void>
internal::return_value< RT >::reference_type Threads::Task< RT >::return_value ( )
inline

Get the return value of the function of the task. Since it is only available once the thread finishes, this function internally also calls join(). You can call this function multiple times as long as the object refers to the same task, and expect to get the same return value every time. (With the exception of the case where the returned object has been moved; see below.)

Note
The function returns a non-const reference to the returned object, instead of the returned object. This allows writing code such as
Threads::Task<int> t = Threads::new_task (...function returning an
int...); t.return_value() = 42; // overwrite returned value int i =
t.return_value(); // i is now 42
internal::return_value< RT >::reference_type return_value()
You will rarely have a need to write such code. On the other hand, the function needs to return a writable (non-const) reference to support code such as this:
std::unique_ptr<int> create_int (const std::string &s) { ... }
void f()
{
t = Threads::new_task (&create_int, "42");
std::unique_ptr<int> i = std::move(t.return_value());
...
}
Here, it is necessary to std::move the returned object (namely, the std::unique_ptr object) because std::unique_ptr objects can not be copied. In other words, to get the pointer out of the object returned from the task, it needs to be moved, and in order to be moved, the current function needs to return a writable (non-const) reference.

This function internally calls the join() member function. As a consequence, and as explained there, if the packaged task throws an exception that is then re-thrown by the join() function and consequently also the current function if you have not previously called join().

Precondition
You can't call this function if you have used the default constructor of this class and have not assigned a task object to it. In other words, the function joinable() must return true.

Definition at line 815 of file thread_management.h.

Member Data Documentation

◆ task_data

template<typename RT = void>
std::shared_ptr<TaskData> Threads::Task< RT >::task_data
private

A pointer to a descriptor of the object that described the task and its return value.

Definition at line 1127 of file thread_management.h.


The documentation for this class was generated from the following file: