1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
When a thread activates an asynchronous provider (e.g., a tt(std::async)) then
the return value of the asynchronously called function becomes available in
its activating thread through a tt(std::future) object. The
tt(future) object cannot be used by another thread. If this is required (e.g.,
see this chapter's final section) the tt(future) object must be converted to a
hi(shared_future)tt(std::shared_future) object.
Before using the class tt(std::shared_future) the tthi(future) header file
must be included.
Once a tt(shared_future) object is available, its tt(get) member (see below)
can repeatedly be called to retrieve the results of the original tt(future)
object. This is illustrated by the next small example:
verbinclude(-ns4 //code examples/sharedfuture.cc)
In lines 9 and 10 the tt(promise's) results are retrieved multiple times,
but having obtained the tt(shared_future) in line 7, the original tt(future)
object no longer has an associated shared state. Therefore, when another
attempt is made (in line 13) to obtain the tt(shared_future), a em(no
associated state) exception is thrown and the program aborts.
However, multiple copies of tt(shared_future) objects may co-exist. When
multiple copies of tt(shared_future) objects exist (e.g. in different
threads), the results of the associated asynchronous task are made ready
(become available) at exactly the same moment in time.
The relationship between the classes tt(future) and tt(shared_future)
resembles the relationship between the classes tt(unique_ptr) and
tt(shared_ptr): there can only be one instance of a tt(unique_pointer),
pointing to data, whereas there can be many instances of a tt(shared_pointer),
each pointing to the same data.
The effect of calling any member of a tt(shared_future) object for which
tt(valid() == false) other than the destructor, the move-assignment operator,
or tt(valid) is undefined.
The class tt(shared_future) supports the following constructors:
itemization(
itt(shared_future() noexcept)
quote(an empty tt(shared_future) object is constructed that does not
refer to shared results. After using this constructor the object's
tt(valid) member returns tt(false).)
itt(shared_future(shared_future const &other))
quote(a tt(shared_future) object is constructed that refers to the
same results as tt(other) (if any). After using this constructor
the object's tt(valid) member returns the same value as
tt(other.valid()).)
itt(shared_future(shared_future<Result> &&tmp) noexcept)
quote( Effects: move constructs a shared_future object that refers to
the results that were originally referred to by tt(tmp) (if
any). After using this constructor the object's tt(valid) member
returns the same value as tt(tmp.valid()) returned prior to the
constructor invocation, and tt(tmp.valid()) returns tt(false).)
itt(shared_future(future<Result> &&tmp) noexcept)
quote( Effects: move constructs a shared_future object that refers to
the results that were originally referred to by tt(tmp) (if
any). After using this constructor the object's tt(valid) member
returns the same value as tt(tmp.valid()) returned prior to the
constructor invocation, and tt(tmp.valid()) returns tt(false).)
)
The class's destructor destroys the tt(shared_future) object for which it is
called. If the object for which the destructor is called is the last
tt(shared_future) object, and no tt(std::promise) or
tt(std::packaged_task) is associated with the results associated
with the current object, then the results are also destroyed.
Here are the members of the class tt(std::shared_future):
itemization(
ittq(shared_future& operator=(shared_future &&tmp))
(The move assignment operator releases the current object's shared
results, and move assigns tt(tmp's) results to the current
object. After calling the move assignment operator the current
object's tt(valid) member returns the same value as tt(tmp.valid())
returned prior to the invocation of the move assignment operator, and
tt(tmp.valid()) returns tt(false);)
ittq(shared_future& operator=(shared_future const &rhs))
(The assignment operator releases the current object's shared results,
and tt(rhs)'s results are shared with the current object. After
calling the assignment operator the current object's tt(valid) member
returns the same value as tt(tmp.valid());)
ittq(Result const &shared_future::get() const)
((Specializations for tt(shared_future<Result &>) and
tt(shared_future<void>) are also available). This member waits until
the shared results are available, and subsequently returns tt(Result
const &). Note that access to the data stored in tt(Results), accessed
through tt(get) is not synchronized. It is the responsibility of the
programmer to avoid race conditions when accessing tt(Result's)
data. If tt(Result) holds an exception, it is thrown when tt(get) is
called;)
ittq(bool valid() const)
(Returns tt(true) if the current object refers to shared
results;)
ittq(void wait() const)
(Blocks until shared results are available (i.e., the associated
asynchronous task has produced results);)
ittq(future_status wait_for(const chrono::duration<Rep, Period>& rel_time)
const)
((The template types tt(Rep) and tt(Period) normally are derived by the
compiler from the actual tt(rel_time) specification.) If the shared
results contain a deferred function (cf. section ref(ASYNC)) nothing
happens. Otherwise tt(wait_for) blocks until the results of the
associated asynchronous task has produced results, or until the
relative time specified by tt(rel_time) has expired. The member
returns
itemization(
itt(future_status::deferred) if the shared results contain a
deferred function; itt(future_status::ready) if the shared results
are available;
itt(future_status::timeout) if the function is returning because
the amount of time specified by tt(rel_time) has expired;)
)
ittq(future_status wait_until(const chrono::time_point<Clock, Duration>&
abs_time) const)
((The template types tt(Clock) and tt(Duration) normally are derived by
the compiler from the actual tt(abs_time) specification.) If the
shared results contain a deferred function nothing happens. Otherwise
tt(wait_until) blocks until the shared results are available or until
the point in time specified by tt(abs_time) has expired. Possible
return values are:
itemization(
itt(future_status::deferred) if the shared results contain a
deferred function;
itt(future_status::ready) if the shared results are available;
itt(future_status::timeout) if the function is returning because
the point in time specified by tt(abs_time) has expired.
)
)
)
|