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