Panda3D
Loading...
Searching...
No Matches
asyncFuture.I
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file asyncFuture.I
10 * @author rdb
11 * @date 2017-11-28
12 */
13
14/**
15 * Initializes the future in the pending state.
16 */
19 _manager(nullptr),
20 _result(nullptr),
21 _future_state(FS_pending) {
22}
23
24/**
25 * Returns true if the future is done or has been cancelled. It is always
26 * safe to call this.
27 */
28INLINE bool AsyncFuture::
29done() const {
30 return (FutureState)AtomicAdjust::get(_future_state) >= FS_finished;
31}
32
33/**
34 * Returns true if the future was cancelled. It is always safe to call this.
35 */
36INLINE bool AsyncFuture::
37cancelled() const {
38 return (FutureState)AtomicAdjust::get(_future_state) == FS_cancelled;
39}
40
41/**
42 * Sets the event name that will be triggered when the future finishes. Will
43 * not be triggered if the future is cancelled, but it will be triggered for
44 * a coroutine task that exits with an exception.
45 */
46INLINE void AsyncFuture::
47set_done_event(const std::string &done_event) {
48 nassertv(!done());
49 _done_event = done_event;
50}
51
52/**
53 * Returns the event name that will be triggered when the future finishes.
54 * See set_done_event().
55 */
56INLINE const std::string &AsyncFuture::
57get_done_event() const {
58 return _done_event;
59}
60
61/**
62 * Returns this future's result. Can only be called if done() returns true.
63 */
65get_result() const {
66 // This is thread safe, since _result may no longer be modified after the
67 // state is changed to "done".
68 nassertr_always(done(), nullptr);
69 return _result;
70}
71
72/**
73 * Returns this future's result as a pair of TypedObject, ReferenceCount
74 * pointers. Can only be called if done() returns true.
75 */
76INLINE void AsyncFuture::
77get_result(TypedObject *&ptr, ReferenceCount *&ref_ptr) const {
78 // This is thread safe, since _result may no longer be modified after the
79 // state is changed to "done".
80 nassertd(done()) {
81 ptr = nullptr;
82 ref_ptr = nullptr;
83 }
84 ptr = _result;
85 ref_ptr = _result_ref.p();
86}
87
88/**
89 * Sets this future's result. Can only be called if done() returns false.
90 */
91INLINE void AsyncFuture::
92set_result(std::nullptr_t) {
93 set_result(nullptr, nullptr);
94}
95
96INLINE void AsyncFuture::
97set_result(TypedObject *result) {
98 set_result(result, nullptr);
99}
100
101INLINE void AsyncFuture::
103 set_result(result, result);
104}
105
106INLINE void AsyncFuture::
108 set_result(result, result);
109}
110
111INLINE void AsyncFuture::
112set_result(const EventParameter &result) {
113 set_result(result.get_ptr(), result.get_ptr());
114}
115
116/**
117 * Creates a new future that returns `done()` when all of the contained
118 * futures are done.
119 *
120 * Calling `cancel()` on the returned future will result in all contained
121 * futures that have not yet finished to be cancelled.
122 */
124gather(Futures futures) {
125 if (futures.empty()) {
126 AsyncFuture *fut = new AsyncFuture;
127 fut->_future_state = (AtomicAdjust::Integer)FS_finished;
128 return fut;
129 } else if (futures.size() == 1) {
130 return futures[0].p();
131 } else {
132 return (AsyncFuture *)new AsyncGatheringFuture(std::move(futures));
133 }
134}
135
136/**
137 * Tries to atomically lock the future, assuming it is pending. Returns false
138 * if it is not in the pending state, implying it's either done or about to be
139 * cancelled.
140 */
141INLINE bool AsyncFuture::
142try_lock_pending() {
143 return set_future_state(FS_locked_pending);
144}
145
146/**
147 * Should be called after try_lock_pending() returns true.
148 */
149INLINE void AsyncFuture::
150unlock(FutureState new_state) {
151 nassertv(new_state != FS_locked_pending);
152 FutureState orig_state = (FutureState)AtomicAdjust::set(_future_state, (AtomicAdjust::Integer)new_state);
153 nassertv(orig_state == FS_locked_pending);
154}
155
156/**
157 * Atomically changes the future state from pending to another state. Returns
158 * true if successful, false if the future was already done.
159 * Note that once a future is in a "done" state (ie. cancelled or finished) it
160 * can never change state again.
161 */
162INLINE bool AsyncFuture::
163set_future_state(FutureState state) {
164 FutureState orig_state = (FutureState)
166 _future_state,
167 (AtomicAdjust::Integer)FS_pending,
168 (AtomicAdjust::Integer)state);
169
170 while (orig_state == FS_locked_pending) {
172 orig_state = (FutureState)AtomicAdjust::compare_and_exchange(
173 _future_state,
174 (AtomicAdjust::Integer)FS_pending,
175 (AtomicAdjust::Integer)state);
176 }
177
178 return orig_state == FS_pending;
179}
180
181/**
182 * Returns the number of futures that were passed to the constructor.
183 */
185get_num_futures() const {
186 return _futures.size();
187}
188
189/**
190 * Returns the nth future that was passed into the constructor.
191 */
193get_future(size_t i) const {
194 nassertr(i < _futures.size(), nullptr);
195 return _futures[i].p();
196}
197
198/**
199 * Returns the result of the nth future that was passed into the constructor.
200 */
202get_result(size_t i) const {
203 nassertr(i < _futures.size(), nullptr);
204 return _futures[i]->get_result();
205}
This class represents a thread-safe handle to a promised future result of an asynchronous operation,...
Definition asyncFuture.h:61
bool cancelled() const
Returns true if the future was cancelled.
Definition asyncFuture.I:37
void set_result(std::nullptr_t)
Sets this future's result.
Definition asyncFuture.I:92
set_done_event
Sets the event name that will be triggered when the future finishes.
Definition asyncFuture.h:77
AsyncFuture()
Initializes the future in the pending state.
Definition asyncFuture.I:18
get_done_event
Returns the event name that will be triggered when the future finishes.
Definition asyncFuture.h:77
TypedObject * get_result() const
Returns this future's result.
Definition asyncFuture.I:65
static AsyncFuture * gather(Futures futures)
Creates a new future that returns `done()` when all of the contained futures are done.
bool done() const
Returns true if the future is done or has been cancelled.
Definition asyncFuture.I:29
Specific future that collects the results of several futures.
size_t get_num_futures() const
Returns the number of futures that were passed to the constructor.
AsyncFuture * get_future(size_t i) const
Returns the nth future that was passed into the constructor.
static Integer set(Integer &var, Integer new_value)
Atomically changes the indicated variable and returns the original value.
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
An optional parameter associated with an event.
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
A base class for all things that want to be reference-counted.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Definition thread.I:201
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition typedObject.h:88
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.