Monado OpenXR Runtime
xrt_future.h
Go to the documentation of this file.
1// Copyright 2025, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Interface for creating futures.
6 * @author Korcan Hussein <korcan.hussein@collabora.com>
7 * @ingroup xrt_iface
8 */
9#pragma once
10
11#include "xrt/xrt_defines.h"
13
14#include <assert.h>
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20/*!
21 * The (future) status of an asynchronous operation
22 *
23 * @see xrt_future::get_state
24 */
25typedef enum xrt_future_state
26{
27 XRT_FUTURE_STATE_PENDING,
28 XRT_FUTURE_STATE_READY,
29 XRT_FUTURE_STATE_CANCELLED,
31
32/*!
33 * The (future) result of an asynchronous operation
34 *
35 * @see xrt_future::get_result, xrt_future::complete
36 */
38{
39 /*!
40 * The result value of a successfully completed asynchronous operation
41 * @see xrt_future_value_make
42 */
43 struct xrt_future_value value;
44
45 //! The error/ok status of a completed asynchronous operation
47};
48
49#define XRT_FUTURE_RESULT(TYPED_VALUE, ERR_CODE) \
50 XRT_C11_COMPOUND(struct xrt_future_result) \
51 { \
52 .value = xrt_future_value_make(TYPED_VALUE), .result = ERR_CODE, \
53 }
54
55/*!
56 * @interface xrt_future
57 * @ingroup xrt_iface
58 *
59 * @brief A future is a concurrency primitive that provides a mechanism to access results of asynchronous operations.
60 *
61 * The xrt_future interface shares similarities with OpenXR futures but is not identical. In comparison to C++
62 * std::future, xrt_future combines concepts from both std::shared_future and std::promise with built-in
63 * cancellation support in a single interface. The interface provides separate method sets for producers
64 * (result generators) and consumers (result pollers/waiters).
65 *
66 * Thread Safety and Reference Counting:
67 * Each thread that references an xrt_future must properly manage the reference count using
68 * @ref xrt_future_reference when entering and exiting the thread's scope.
69 *
70 * @see "Server-side / driver — implementing async callbacks" in @ref
71 * [async-functions-and-futures](../../../../doc/async-functions-and-futures.md) for producer example code
72 */
74{
75 /*!
76 * Reference helper.
77 */
78 struct xrt_reference reference;
79
80 /*!
81 * Destroys the future.
82 */
83 void (*destroy)(struct xrt_future *xft);
84
85 /*!
86 * @brief Gets the current state of the future
87 *
88 * @param[in] xft The future.
89 * @param[out] out_state The current state of @ref xft
90 *
91 * @note Consumer Interface
92 *
93 * @note Blocking behavior - non-blocking
94 *
95 * @see xrt_future_state
96 */
97 xrt_result_t (*get_state)(const struct xrt_future *xft, enum xrt_future_state *out_state);
98
99 /*!
100 * @brief Gets the future results (after async operation has finished)
101 *
102 * @param[in] xft The future.
103 * @param[out] out_result The future result of @ref xft
104 *
105 * @note Consumer Interface
106 *
107 * @note Blocking behavior - Non-blocking w.r.t. result: returns immediately,
108 * may briefly block acquiring an internal mutex to check/consume state
109 *
110 * @note differs from std::future::get in that std::future will block & wait the calling thread
111 * until the result is ready where as xrt_future::get_result is non-blocking (w.r.t. result)
112 * to achieve the equivalent without using polling interface would be:
113 *
114 * // std::future::get ==
115 * xrt_future_wait(xft, INT64_MAX);
116 * xrt_get_result(xft, &my_result);
117 *
118 * @note Similar to or used by OpenXR future/async complete functions
119 *
120 * @see xrt_future::complete, xrt_future_result, xrt_future_value
121 */
122 xrt_result_t (*get_result)(const struct xrt_future *xft, struct xrt_future_result *out_result);
123
124 /*!
125 * @brief Signals an asynchronous operation associated with the future to cancel.
126 *
127 * @param[in] xft The future.
128 *
129 * @note Consumer Interface
130 *
131 * @note Blocking behavior - Non-blocking, may briefly block acquiring an internal mutex to check/consume state
132 */
133 xrt_result_t (*cancel)(struct xrt_future *xft);
134
135 /*!
136 * @brief Waits on a pending/cancelled future
137 *
138 * @param[in] xft The future.
139 * @param[in] timeout_ns Timeout in nanoseconds or INT64_MAX for infinite duration
140 *
141 * @note Consumer Interface
142 *
143 * @note Blocking behavior - Blocking
144 *
145 * @see xrt_future::cancel, xrt_future::complete
146 */
147 xrt_result_t (*wait)(struct xrt_future *xft, int64_t timeout_ns);
148
149 /*!
150 * @brief Waits on a cancelled future
151 *
152 * @param[in] xft The future.
153 * @param[out] out_request_cancel Has the consumer requested to cancel the async operation?
154 *
155 * @note Producer interface
156 *
157 * @note Blocking behavior - non-blocking
158 *
159 * @see xrt_future::cancel
160 */
161 xrt_result_t (*is_cancel_requested)(const struct xrt_future *xft, bool *out_request_cancel);
162
163 /*!
164 * @brief Signals that the asynchronous operation has completed and sets the future’s result.
165 *
166 * @param[in] xft The future.
167 * @param[in] ft_result the result of an async operation associated with @ref xft.
168 *
169 * @note Producer interface
170 *
171 * @note Blocking behavior - Non-blocking, may briefly block acquiring an internal mutex to check/consume state
172 *
173 * @note Differs from OpenXR future/async complete functions as those are used to only get the results of
174 * a future once the async-operation has finished where as this callback is used by async operation
175 * to mark/signal completion and return a result
176 *
177 * @note Similar to std::promise::set_value
178 *
179 * @see xrt_future::get_result, xrt_future_result, xrt_future_value
180 */
181 xrt_result_t (*complete)(struct xrt_future *xft, const struct xrt_future_result *ft_result);
182};
183
184/*!
185 * Update the reference counts on xrt_future(s).
186 *
187 * @param[in,out] dst Pointer to a object reference: if the object reference is
188 * non-null will decrement its counter. The reference that
189 * @p dst points to will be set to @p src.
190 * @param[in] src New object for @p dst to refer to (may be null).
191 * If non-null, will have its refcount increased.
192 * @ingroup xrt_iface
193 * @relates xrt_future
194 */
195static inline void
197{
198 struct xrt_future *old_dst = *dst;
199
200 if (old_dst == src) {
201 return;
202 }
203
204 if (src) {
205 xrt_reference_inc(&src->reference);
206 }
207
208 *dst = src;
209
210 if (old_dst) {
211 if (xrt_reference_dec_and_is_zero(&old_dst->reference)) {
212 assert(old_dst->destroy);
213 old_dst->destroy(old_dst);
214 }
215 }
216}
217
218/*!
219 * Helper function for @ref xrt_future::get_result.
220 *
221 * @copydoc xrt_future::get_result
222 *
223 * @public @memberof xrt_future
224 */
225static inline xrt_result_t
226xrt_future_get_result(const struct xrt_future *xft, struct xrt_future_result *out_result)
227{
228 assert(xft && xft->get_result);
229 return xft->get_result(xft, out_result);
230}
231
232/*!
233 * Helper function for @ref xrt_future::get_state.
234 *
235 * @copydoc xrt_future::get_state
236 *
237 * @public @memberof xrt_future
238 */
239static inline xrt_result_t
240xrt_future_get_state(const struct xrt_future *xft, enum xrt_future_state *out_state)
241{
242 assert(xft && xft->get_state);
243 return xft->get_state(xft, out_state);
244}
245
246/*!
247 * Helper function for @ref xrt_future::cancel.
248 *
249 * @copydoc xrt_future::cancel
250 *
251 * @public @memberof xrt_future
252 */
253static inline xrt_result_t
255{
256 assert(xft && xft->cancel);
257 return xft->cancel(xft);
258}
259
260/*!
261 * Helper function for @ref xrt_future::wait.
262 *
263 * @copydoc xrt_future::wait
264 *
265 * @public @memberof xrt_future
266 */
267static inline xrt_result_t
268xrt_future_wait(struct xrt_future *xft, int64_t timeout)
269{
270 assert(xft && xft->wait);
271 return xft->wait(xft, timeout);
272}
273
274/*!
275 * Helper function for @ref xrt_future::is_cancel_requested.
276 *
277 * @copydoc xrt_future::is_cancel_requested
278 *
279 * @public @memberof xrt_future
280 */
281static inline xrt_result_t
282xrt_future_is_cancel_requested(const struct xrt_future *xft, bool *out_request_cancel)
283{
284 assert(xft && xft->is_cancel_requested);
285 return xft->is_cancel_requested(xft, out_request_cancel);
286}
287
288/*!
289 * Helper function for @ref xrt_future::complete.
290 *
291 * @copydoc xrt_future::complete
292 *
293 * @public @memberof xrt_future
294 */
295static inline xrt_result_t
296xrt_future_complete(struct xrt_future *xft, const struct xrt_future_result *ft_result)
297{
298 assert(xft && xft->complete);
299 return xft->complete(xft, ft_result);
300}
301
302#ifdef __cplusplus
303}
304#endif
static void xrt_future_reference(struct xrt_future **dst, struct xrt_future *src)
Update the reference counts on xrt_future(s).
Definition: xrt_future.h:196
enum xrt_result xrt_result_t
Result type used across Monado.
The (future) result of an asynchronous operation.
Definition: xrt_future.h:38
XRT_ALIGNAS(8) xrt_result_t result
The error/ok status of a completed asynchronous operation.
Definition: xrt_future_value.h:46
A future is a concurrency primitive that provides a mechanism to access results of asynchronous opera...
Definition: xrt_future.h:74
static xrt_result_t xrt_future_complete(struct xrt_future *xft, const struct xrt_future_result *ft_result)
Helper function for xrt_future::complete.
Definition: xrt_future.h:296
static xrt_result_t xrt_future_get_result(const struct xrt_future *xft, struct xrt_future_result *out_result)
Helper function for xrt_future::get_result.
Definition: xrt_future.h:226
xrt_result_t(* complete)(struct xrt_future *xft, const struct xrt_future_result *ft_result)
Signals that the asynchronous operation has completed and sets the future’s result.
Definition: xrt_future.h:181
xrt_result_t(* is_cancel_requested)(const struct xrt_future *xft, bool *out_request_cancel)
Waits on a cancelled future.
Definition: xrt_future.h:161
xrt_result_t(* get_result)(const struct xrt_future *xft, struct xrt_future_result *out_result)
Gets the future results (after async operation has finished)
Definition: xrt_future.h:122
xrt_result_t(* wait)(struct xrt_future *xft, int64_t timeout_ns)
Waits on a pending/cancelled future.
Definition: xrt_future.h:147
static xrt_result_t xrt_future_get_state(const struct xrt_future *xft, enum xrt_future_state *out_state)
Helper function for xrt_future::get_state.
Definition: xrt_future.h:240
static xrt_result_t xrt_future_wait(struct xrt_future *xft, int64_t timeout)
Helper function for xrt_future::wait.
Definition: xrt_future.h:268
xrt_result_t(* get_state)(const struct xrt_future *xft, enum xrt_future_state *out_state)
Gets the current state of the future.
Definition: xrt_future.h:97
void(* destroy)(struct xrt_future *xft)
Destroys the future.
Definition: xrt_future.h:83
static xrt_result_t xrt_future_cancel(struct xrt_future *xft)
Helper function for xrt_future::cancel.
Definition: xrt_future.h:254
xrt_result_t(* cancel)(struct xrt_future *xft)
Signals an asynchronous operation associated with the future to cancel.
Definition: xrt_future.h:133
struct xrt_reference reference
Reference helper.
Definition: xrt_future.h:78
static xrt_result_t xrt_future_is_cancel_requested(const struct xrt_future *xft, bool *out_request_cancel)
Helper function for xrt_future::is_cancel_requested.
Definition: xrt_future.h:282
A base class for reference counted objects.
Definition: xrt_defines.h:98
Common defines and enums for XRT.
xrt_future_state
The (future) status of an asynchronous operation.
Definition: xrt_future.h:26
enum xrt_future_state xrt_future_state_t
The (future) status of an asynchronous operation.
Variant/algebraic data-type for holding the values of xrt_futures.