From 97ea59f6d428b3942cfc0fb6909af2e517b36e72 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Sun, 1 Apr 2018 11:00:52 -0600 Subject: [PATCH] Update description of Thread/Task::return_value(). --- include/deal.II/base/thread_management.h | 94 +++++++++++++++++++++--- 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/include/deal.II/base/thread_management.h b/include/deal.II/base/thread_management.h index ed332ba1bd..087a49cb24 100644 --- a/include/deal.II/base/thread_management.h +++ b/include/deal.II/base/thread_management.h @@ -683,9 +683,10 @@ namespace Threads /** * @internal * - * Given an arbitrary type RT, store an element of it and grant access to - * it through functions get() and set(). There are specializations for - * reference types (which cannot be set), and for type void. + * Given an arbitrary type RT, store an element of it and grant + * access to it through functions get() and set(). There are + * specializations for reference types (which need to be stored as + * pointers to the object being referenced), and for type void. */ template struct return_value { @@ -713,8 +714,8 @@ namespace Threads * * Given an arbitrary type RT, store an element of it and grant access to * it through functions get() and set(). This is the specialization for - * reference types: since they cannot be set after construction time, we - * store a pointer instead, that holds the address of the object being + * reference types: since references cannot be set after construction time, we + * store a pointer instead, which holds the address of the object being * referenced. */ template struct return_value @@ -1029,8 +1030,43 @@ namespace Threads } /** - * Get the return value of the function of the thread. Since this is only - * available once the thread finishes, this implicitly also calls join(). + * Get the return value of the function of the thread. 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-@p const reference to + * the returned object, instead of the returned object. This + * allows writing code such as + * @code + * Threads::Thread t = Threads::new_thread (...function returning an int...); + * t.return_value() = 42; // overwrite returned value + * int i = t.return_value(); // i is now 42 + * @endcode + * You will rarely have a need to write such code. On the other hand, + * the function needs to return a writable reference to support + * code such as this: + * @code + * std::unique_ptr create_int (const std::string &s) { ... } + * + * void f() + * { + * Threads::Thread> + * t = Threads::new_thread (&create_int, "42"); + * + * std::unique_ptr i = std::move(t.return_value()); + * ... + * } + * @endcode + * 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 thread, it needs + * to be moved, and in order to be moved, the current function needs to + * return a writable reference. */ typename internal::return_value::reference_type return_value () @@ -1701,16 +1737,50 @@ namespace Threads /** - * Get the return value of the function of the task. Since this is only - * available once the task finishes, this implicitly 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. + * 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-@p const reference to + * the returned object, instead of the returned object. This + * allows writing code such as + * @code + * Threads::Task t = Threads::new_task (...function returning an int...); + * t.return_value() = 42; // overwrite returned value + * int i = t.return_value(); // i is now 42 + * @endcode + * You will rarely have a need to write such code. On the other hand, + * the function needs to return a writable reference to support + * code such as this: + * @code + * std::unique_ptr create_int (const std::string &s) { ... } + * + * void f() + * { + * Threads::Task> + * t = Threads::new_task (&create_int, "42"); + * + * std::unique_ptr i = std::move(t.return_value()); + * ... + * } + * @endcode + * 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 reference. * * @pre 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. */ - typename internal::return_value::reference_type return_value () + typename internal::return_value::reference_type + return_value () { join (); return task_descriptor->ret_val.get(); -- 2.39.5