sdl3_sys/generated/asyncio.rs
1//! SDL offers a way to perform I/O asynchronously. This allows an app to read
2//! or write files without waiting for data to actually transfer; the functions
3//! that request I/O never block while the request is fulfilled.
4//!
5//! Instead, the data moves in the background and the app can check for results
6//! at their leisure.
7//!
8//! This is more complicated than just reading and writing files in a
9//! synchronous way, but it can allow for more efficiency, and never having
10//! framerate drops as the hard drive catches up, etc.
11//!
12//! The general usage pattern for async I/O is:
13//!
14//! - Create one or more [`SDL_AsyncIOQueue`] objects.
15//! - Open files with [`SDL_AsyncIOFromFile`].
16//! - Start I/O tasks to the files with [`SDL_ReadAsyncIO`] or [`SDL_WriteAsyncIO`],
17//! putting those tasks into one of the queues.
18//! - Later on, use [`SDL_GetAsyncIOResult`] on a queue to see if any task is
19//! finished without blocking. Tasks might finish in any order with success
20//! or failure.
21//! - When all your tasks are done, close the file with [`SDL_CloseAsyncIO`]. This
22//! also generates a task, since it might flush data to disk!
23//!
24//! This all works, without blocking, in a single thread, but one can also wait
25//! on a queue in a background thread, sleeping until new results have arrived:
26//!
27//! - Call [`SDL_WaitAsyncIOResult`] from one or more threads to efficiently block
28//! until new tasks complete.
29//! - When shutting down, call [`SDL_SignalAsyncIOQueue`] to unblock any sleeping
30//! threads despite there being no new tasks completed.
31//!
32//! And, of course, to match the synchronous [`SDL_LoadFile`], we offer
33//! [`SDL_LoadFileAsync`] as a convenience function. This will handle allocating a
34//! buffer, slurping in the file data, and null-terminating it; you still check
35//! for results later.
36//!
37//! Behind the scenes, SDL will use newer, efficient APIs on platforms that
38//! support them: Linux's io_uring and Windows 11's IoRing, for example. If
39//! those technologies aren't available, SDL will offload the work to a thread
40//! pool that will manage otherwise-synchronous loads without blocking the app.
41//!
42//! ## Best Practices
43//!
44//! Simple non-blocking I/O--for an app that just wants to pick up data
45//! whenever it's ready without losing framerate waiting on disks to spin--can
46//! use whatever pattern works well for the program. In this case, simply call
47//! [`SDL_ReadAsyncIO`], or maybe [`SDL_LoadFileAsync`], as needed. Once a frame, call
48//! [`SDL_GetAsyncIOResult`] to check for any completed tasks and deal with the
49//! data as it arrives.
50//!
51//! If two separate pieces of the same program need their own I/O, it is legal
52//! for each to create their own queue. This will prevent either piece from
53//! accidentally consuming the other's completed tasks. Each queue does require
54//! some amount of resources, but it is not an overwhelming cost. Do not make a
55//! queue for each task, however. It is better to put many tasks into a single
56//! queue. They will be reported in order of completion, not in the order they
57//! were submitted, so it doesn't generally matter what order tasks are
58//! started.
59//!
60//! One async I/O queue can be shared by multiple threads, or one thread can
61//! have more than one queue, but the most efficient way--if ruthless
62//! efficiency is the goal--is to have one queue per thread, with multiple
63//! threads working in parallel, and attempt to keep each queue loaded with
64//! tasks that are both started by and consumed by the same thread. On modern
65//! platforms that can use newer interfaces, this can keep data flowing as
66//! efficiently as possible all the way from storage hardware to the app, with
67//! no contention between threads for access to the same queue.
68//!
69//! Written data is not guaranteed to make it to physical media by the time a
70//! closing task is completed, unless [`SDL_CloseAsyncIO`] is called with its
71//! `flush` parameter set to true, which is to say that a successful result
72//! here can still result in lost data during an unfortunately-timed power
73//! outage if not flushed. However, flushing will take longer and may be
74//! unnecessary, depending on the app's needs.
75
76use super::stdinc::*;
77
78/// Types of asynchronous I/O tasks.
79///
80/// ## Availability
81/// This enum is available since SDL 3.2.0.
82///
83/// ## Known values (`sdl3-sys`)
84/// | Associated constant | Global constant | Description |
85/// | ------------------- | --------------- | ----------- |
86/// | [`READ`](SDL_AsyncIOTaskType::READ) | [`SDL_ASYNCIO_TASK_READ`] | A read operation. |
87/// | [`WRITE`](SDL_AsyncIOTaskType::WRITE) | [`SDL_ASYNCIO_TASK_WRITE`] | A write operation. |
88/// | [`CLOSE`](SDL_AsyncIOTaskType::CLOSE) | [`SDL_ASYNCIO_TASK_CLOSE`] | A close operation. |
89#[repr(transparent)]
90#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
91pub struct SDL_AsyncIOTaskType(pub ::core::ffi::c_int);
92
93impl ::core::cmp::PartialEq<::core::ffi::c_int> for SDL_AsyncIOTaskType {
94 #[inline(always)]
95 fn eq(&self, other: &::core::ffi::c_int) -> bool {
96 &self.0 == other
97 }
98}
99
100impl ::core::cmp::PartialEq<SDL_AsyncIOTaskType> for ::core::ffi::c_int {
101 #[inline(always)]
102 fn eq(&self, other: &SDL_AsyncIOTaskType) -> bool {
103 self == &other.0
104 }
105}
106
107impl From<SDL_AsyncIOTaskType> for ::core::ffi::c_int {
108 #[inline(always)]
109 fn from(value: SDL_AsyncIOTaskType) -> Self {
110 value.0
111 }
112}
113
114#[cfg(feature = "debug-impls")]
115impl ::core::fmt::Debug for SDL_AsyncIOTaskType {
116 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
117 #[allow(unreachable_patterns)]
118 f.write_str(match *self {
119 Self::READ => "SDL_ASYNCIO_TASK_READ",
120 Self::WRITE => "SDL_ASYNCIO_TASK_WRITE",
121 Self::CLOSE => "SDL_ASYNCIO_TASK_CLOSE",
122
123 _ => return write!(f, "SDL_AsyncIOTaskType({})", self.0),
124 })
125 }
126}
127
128impl SDL_AsyncIOTaskType {
129 /// A read operation.
130 pub const READ: Self = Self((0 as ::core::ffi::c_int));
131 /// A write operation.
132 pub const WRITE: Self = Self((1 as ::core::ffi::c_int));
133 /// A close operation.
134 pub const CLOSE: Self = Self((2 as ::core::ffi::c_int));
135}
136
137/// A read operation.
138pub const SDL_ASYNCIO_TASK_READ: SDL_AsyncIOTaskType = SDL_AsyncIOTaskType::READ;
139/// A write operation.
140pub const SDL_ASYNCIO_TASK_WRITE: SDL_AsyncIOTaskType = SDL_AsyncIOTaskType::WRITE;
141/// A close operation.
142pub const SDL_ASYNCIO_TASK_CLOSE: SDL_AsyncIOTaskType = SDL_AsyncIOTaskType::CLOSE;
143
144#[cfg(feature = "metadata")]
145impl sdl3_sys::metadata::GroupMetadata for SDL_AsyncIOTaskType {
146 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
147 &crate::metadata::asyncio::METADATA_SDL_AsyncIOTaskType;
148}
149
150/// Possible outcomes of an asynchronous I/O task.
151///
152/// ## Availability
153/// This enum is available since SDL 3.2.0.
154///
155/// ## Known values (`sdl3-sys`)
156/// | Associated constant | Global constant | Description |
157/// | ------------------- | --------------- | ----------- |
158/// | [`COMPLETE`](SDL_AsyncIOResult::COMPLETE) | [`SDL_ASYNCIO_COMPLETE`] | request was completed without error |
159/// | [`FAILURE`](SDL_AsyncIOResult::FAILURE) | [`SDL_ASYNCIO_FAILURE`] | request failed for some reason; check [`SDL_GetError()`]! |
160/// | [`CANCELED`](SDL_AsyncIOResult::CANCELED) | [`SDL_ASYNCIO_CANCELED`] | request was canceled before completing. |
161#[repr(transparent)]
162#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
163pub struct SDL_AsyncIOResult(pub ::core::ffi::c_int);
164
165impl ::core::cmp::PartialEq<::core::ffi::c_int> for SDL_AsyncIOResult {
166 #[inline(always)]
167 fn eq(&self, other: &::core::ffi::c_int) -> bool {
168 &self.0 == other
169 }
170}
171
172impl ::core::cmp::PartialEq<SDL_AsyncIOResult> for ::core::ffi::c_int {
173 #[inline(always)]
174 fn eq(&self, other: &SDL_AsyncIOResult) -> bool {
175 self == &other.0
176 }
177}
178
179impl From<SDL_AsyncIOResult> for ::core::ffi::c_int {
180 #[inline(always)]
181 fn from(value: SDL_AsyncIOResult) -> Self {
182 value.0
183 }
184}
185
186#[cfg(feature = "debug-impls")]
187impl ::core::fmt::Debug for SDL_AsyncIOResult {
188 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
189 #[allow(unreachable_patterns)]
190 f.write_str(match *self {
191 Self::COMPLETE => "SDL_ASYNCIO_COMPLETE",
192 Self::FAILURE => "SDL_ASYNCIO_FAILURE",
193 Self::CANCELED => "SDL_ASYNCIO_CANCELED",
194
195 _ => return write!(f, "SDL_AsyncIOResult({})", self.0),
196 })
197 }
198}
199
200impl SDL_AsyncIOResult {
201 /// request was completed without error
202 pub const COMPLETE: Self = Self((0 as ::core::ffi::c_int));
203 /// request failed for some reason; check [`SDL_GetError()`]!
204 pub const FAILURE: Self = Self((1 as ::core::ffi::c_int));
205 /// request was canceled before completing.
206 pub const CANCELED: Self = Self((2 as ::core::ffi::c_int));
207}
208
209/// request was completed without error
210pub const SDL_ASYNCIO_COMPLETE: SDL_AsyncIOResult = SDL_AsyncIOResult::COMPLETE;
211/// request failed for some reason; check [`SDL_GetError()`]!
212pub const SDL_ASYNCIO_FAILURE: SDL_AsyncIOResult = SDL_AsyncIOResult::FAILURE;
213/// request was canceled before completing.
214pub const SDL_ASYNCIO_CANCELED: SDL_AsyncIOResult = SDL_AsyncIOResult::CANCELED;
215
216#[cfg(feature = "metadata")]
217impl sdl3_sys::metadata::GroupMetadata for SDL_AsyncIOResult {
218 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
219 &crate::metadata::asyncio::METADATA_SDL_AsyncIOResult;
220}
221
222/// Information about a completed asynchronous I/O request.
223///
224/// ## Availability
225/// This struct is available since SDL 3.2.0.
226#[repr(C)]
227#[cfg_attr(feature = "debug-impls", derive(Debug))]
228pub struct SDL_AsyncIOOutcome {
229 /// what generated this task. This pointer will be invalid if it was closed!
230 pub asyncio: *mut SDL_AsyncIO,
231 /// What sort of task was this? Read, write, etc?
232 pub r#type: SDL_AsyncIOTaskType,
233 /// the result of the work (success, failure, cancellation).
234 pub result: SDL_AsyncIOResult,
235 /// buffer where data was read/written.
236 pub buffer: *mut ::core::ffi::c_void,
237 /// offset in the [`SDL_AsyncIO`] where data was read/written.
238 pub offset: Uint64,
239 /// number of bytes the task was to read/write.
240 pub bytes_requested: Uint64,
241 /// actual number of bytes that were read/written.
242 pub bytes_transferred: Uint64,
243 /// pointer provided by the app when starting the task
244 pub userdata: *mut ::core::ffi::c_void,
245}
246
247impl ::core::default::Default for SDL_AsyncIOOutcome {
248 /// Initialize all fields to zero
249 #[inline(always)]
250 fn default() -> Self {
251 unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() }
252 }
253}
254
255unsafe extern "C" {
256 /// Use this function to create a new [`SDL_AsyncIO`] object for reading from
257 /// and/or writing to a named file.
258 ///
259 /// The `mode` string understands the following values:
260 ///
261 /// - "r": Open a file for reading only. It must exist.
262 /// - "w": Open a file for writing only. It will create missing files or
263 /// truncate existing ones.
264 /// - "r+": Open a file for update both reading and writing. The file must
265 /// exist.
266 /// - "w+": Create an empty file for both reading and writing. If a file with
267 /// the same name already exists its content is erased and the file is
268 /// treated as a new empty file.
269 ///
270 /// There is no "b" mode, as there is only "binary" style I/O, and no "a" mode
271 /// for appending, since you specify the position when starting a task.
272 ///
273 /// This function supports Unicode filenames, but they must be encoded in UTF-8
274 /// format, regardless of the underlying operating system.
275 ///
276 /// This call is _not_ asynchronous; it will open the file before returning,
277 /// under the assumption that doing so is generally a fast operation. Future
278 /// reads and writes to the opened file will be async, however.
279 ///
280 /// ## Parameters
281 /// - `file`: a UTF-8 string representing the filename to open.
282 /// - `mode`: an ASCII string representing the mode to be used for opening
283 /// the file.
284 ///
285 /// ## Return value
286 /// Returns a pointer to the [`SDL_AsyncIO`] structure that is created or NULL on
287 /// failure; call [`SDL_GetError()`] for more information.
288 ///
289 /// ## Availability
290 /// This function is available since SDL 3.2.0.
291 ///
292 /// ## See also
293 /// - [`SDL_CloseAsyncIO`]
294 /// - [`SDL_ReadAsyncIO`]
295 /// - [`SDL_WriteAsyncIO`]
296 pub fn SDL_AsyncIOFromFile(
297 file: *const ::core::ffi::c_char,
298 mode: *const ::core::ffi::c_char,
299 ) -> *mut SDL_AsyncIO;
300}
301
302unsafe extern "C" {
303 /// Use this function to get the size of the data stream in an [`SDL_AsyncIO`].
304 ///
305 /// This call is _not_ asynchronous; it assumes that obtaining this info is a
306 /// non-blocking operation in most reasonable cases.
307 ///
308 /// ## Parameters
309 /// - `asyncio`: the [`SDL_AsyncIO`] to get the size of the data stream from.
310 ///
311 /// ## Return value
312 /// Returns the size of the data stream in the [`SDL_IOStream`] on success or a
313 /// negative error code on failure; call [`SDL_GetError()`] for more
314 /// information.
315 ///
316 /// ## Thread safety
317 /// It is safe to call this function from any thread.
318 ///
319 /// ## Availability
320 /// This function is available since SDL 3.2.0.
321 pub fn SDL_GetAsyncIOSize(asyncio: *mut SDL_AsyncIO) -> Sint64;
322}
323
324unsafe extern "C" {
325 /// Start an async read.
326 ///
327 /// This function reads up to `size` bytes from `offset` position in the data
328 /// source to the area pointed at by `ptr`. This function may read less bytes
329 /// than requested.
330 ///
331 /// This function returns as quickly as possible; it does not wait for the read
332 /// to complete. On a successful return, this work will continue in the
333 /// background. If the work begins, even failure is asynchronous: a failing
334 /// return value from this function only means the work couldn't start at all.
335 ///
336 /// `ptr` must remain available until the work is done, and may be accessed by
337 /// the system at any time until then. Do not allocate it on the stack, as this
338 /// might take longer than the life of the calling function to complete!
339 ///
340 /// An [`SDL_AsyncIOQueue`] must be specified. The newly-created task will be added
341 /// to it when it completes its work.
342 ///
343 /// ## Parameters
344 /// - `asyncio`: a pointer to an [`SDL_AsyncIO`] structure.
345 /// - `ptr`: a pointer to a buffer to read data into.
346 /// - `offset`: the position to start reading in the data source.
347 /// - `size`: the number of bytes to read from the data source.
348 /// - `queue`: a queue to add the new [`SDL_AsyncIO`] to.
349 /// - `userdata`: an app-defined pointer that will be provided with the task
350 /// results.
351 ///
352 /// ## Return value
353 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
354 /// information.
355 ///
356 /// ## Thread safety
357 /// It is safe to call this function from any thread.
358 ///
359 /// ## Availability
360 /// This function is available since SDL 3.2.0.
361 ///
362 /// ## See also
363 /// - [`SDL_WriteAsyncIO`]
364 /// - [`SDL_CreateAsyncIOQueue`]
365 pub fn SDL_ReadAsyncIO(
366 asyncio: *mut SDL_AsyncIO,
367 ptr: *mut ::core::ffi::c_void,
368 offset: Uint64,
369 size: Uint64,
370 queue: *mut SDL_AsyncIOQueue,
371 userdata: *mut ::core::ffi::c_void,
372 ) -> ::core::primitive::bool;
373}
374
375unsafe extern "C" {
376 /// Start an async write.
377 ///
378 /// This function writes `size` bytes from `offset` position in the data source
379 /// to the area pointed at by `ptr`.
380 ///
381 /// This function returns as quickly as possible; it does not wait for the
382 /// write to complete. On a successful return, this work will continue in the
383 /// background. If the work begins, even failure is asynchronous: a failing
384 /// return value from this function only means the work couldn't start at all.
385 ///
386 /// `ptr` must remain available until the work is done, and may be accessed by
387 /// the system at any time until then. Do not allocate it on the stack, as this
388 /// might take longer than the life of the calling function to complete!
389 ///
390 /// An [`SDL_AsyncIOQueue`] must be specified. The newly-created task will be added
391 /// to it when it completes its work.
392 ///
393 /// ## Parameters
394 /// - `asyncio`: a pointer to an [`SDL_AsyncIO`] structure.
395 /// - `ptr`: a pointer to a buffer to write data from.
396 /// - `offset`: the position to start writing to the data source.
397 /// - `size`: the number of bytes to write to the data source.
398 /// - `queue`: a queue to add the new [`SDL_AsyncIO`] to.
399 /// - `userdata`: an app-defined pointer that will be provided with the task
400 /// results.
401 ///
402 /// ## Return value
403 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
404 /// information.
405 ///
406 /// ## Thread safety
407 /// It is safe to call this function from any thread.
408 ///
409 /// ## Availability
410 /// This function is available since SDL 3.2.0.
411 ///
412 /// ## See also
413 /// - [`SDL_ReadAsyncIO`]
414 /// - [`SDL_CreateAsyncIOQueue`]
415 pub fn SDL_WriteAsyncIO(
416 asyncio: *mut SDL_AsyncIO,
417 ptr: *mut ::core::ffi::c_void,
418 offset: Uint64,
419 size: Uint64,
420 queue: *mut SDL_AsyncIOQueue,
421 userdata: *mut ::core::ffi::c_void,
422 ) -> ::core::primitive::bool;
423}
424
425unsafe extern "C" {
426 /// Close and free any allocated resources for an async I/O object.
427 ///
428 /// Closing a file is _also_ an asynchronous task! If a write failure were to
429 /// happen during the closing process, for example, the task results will
430 /// report it as usual.
431 ///
432 /// Closing a file that has been written to does not guarantee the data has
433 /// made it to physical media; it may remain in the operating system's file
434 /// cache, for later writing to disk. This means that a successfully-closed
435 /// file can be lost if the system crashes or loses power in this small window.
436 /// To prevent this, call this function with the `flush` parameter set to true.
437 /// This will make the operation take longer, and perhaps increase system load
438 /// in general, but a successful result guarantees that the data has made it to
439 /// physical storage. Don't use this for temporary files, caches, and
440 /// unimportant data, and definitely use it for crucial irreplaceable files,
441 /// like game saves.
442 ///
443 /// This function guarantees that the close will happen after any other pending
444 /// tasks to `asyncio`, so it's safe to open a file, start several operations,
445 /// close the file immediately, then check for all results later. This function
446 /// will not block until the tasks have completed.
447 ///
448 /// Once this function returns true, `asyncio` is no longer valid, regardless
449 /// of any future outcomes. Any completed tasks might still contain this
450 /// pointer in their [`SDL_AsyncIOOutcome`] data, in case the app was using this
451 /// value to track information, but it should not be used again.
452 ///
453 /// If this function returns false, the close wasn't started at all, and it's
454 /// safe to attempt to close again later.
455 ///
456 /// An [`SDL_AsyncIOQueue`] must be specified. The newly-created task will be added
457 /// to it when it completes its work.
458 ///
459 /// ## Parameters
460 /// - `asyncio`: a pointer to an [`SDL_AsyncIO`] structure to close.
461 /// - `flush`: true if data should sync to disk before the task completes.
462 /// - `queue`: a queue to add the new [`SDL_AsyncIO`] to.
463 /// - `userdata`: an app-defined pointer that will be provided with the task
464 /// results.
465 ///
466 /// ## Return value
467 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
468 /// information.
469 ///
470 /// ## Thread safety
471 /// It is safe to call this function from any thread, but two
472 /// threads should not attempt to close the same object.
473 ///
474 /// ## Availability
475 /// This function is available since SDL 3.2.0.
476 pub fn SDL_CloseAsyncIO(
477 asyncio: *mut SDL_AsyncIO,
478 flush: ::core::primitive::bool,
479 queue: *mut SDL_AsyncIOQueue,
480 userdata: *mut ::core::ffi::c_void,
481 ) -> ::core::primitive::bool;
482}
483
484unsafe extern "C" {
485 /// Create a task queue for tracking multiple I/O operations.
486 ///
487 /// Async I/O operations are assigned to a queue when started. The queue can be
488 /// checked for completed tasks thereafter.
489 ///
490 /// ## Return value
491 /// Returns a new task queue object or NULL if there was an error; call
492 /// [`SDL_GetError()`] for more information.
493 ///
494 /// ## Thread safety
495 /// It is safe to call this function from any thread.
496 ///
497 /// ## Availability
498 /// This function is available since SDL 3.2.0.
499 ///
500 /// ## See also
501 /// - [`SDL_DestroyAsyncIOQueue`]
502 /// - [`SDL_GetAsyncIOResult`]
503 /// - [`SDL_WaitAsyncIOResult`]
504 pub fn SDL_CreateAsyncIOQueue() -> *mut SDL_AsyncIOQueue;
505}
506
507unsafe extern "C" {
508 /// Destroy a previously-created async I/O task queue.
509 ///
510 /// If there are still tasks pending for this queue, this call will block until
511 /// those tasks are finished. All those tasks will be deallocated. Their
512 /// results will be lost to the app.
513 ///
514 /// Any pending reads from [`SDL_LoadFileAsync()`] that are still in this queue
515 /// will have their buffers deallocated by this function, to prevent a memory
516 /// leak.
517 ///
518 /// Once this function is called, the queue is no longer valid and should not
519 /// be used, including by other threads that might access it while destruction
520 /// is blocking on pending tasks.
521 ///
522 /// Do not destroy a queue that still has threads waiting on it through
523 /// [`SDL_WaitAsyncIOResult()`]. You can call [`SDL_SignalAsyncIOQueue()`] first to
524 /// unblock those threads, and take measures (such as [`SDL_WaitThread()`]) to make
525 /// sure they have finished their wait and won't wait on the queue again.
526 ///
527 /// ## Parameters
528 /// - `queue`: the task queue to destroy.
529 ///
530 /// ## Thread safety
531 /// It is safe to call this function from any thread, so long as
532 /// no other thread is waiting on the queue with
533 /// [`SDL_WaitAsyncIOResult`].
534 ///
535 /// ## Availability
536 /// This function is available since SDL 3.2.0.
537 pub fn SDL_DestroyAsyncIOQueue(queue: *mut SDL_AsyncIOQueue);
538}
539
540unsafe extern "C" {
541 /// Query an async I/O task queue for completed tasks.
542 ///
543 /// If a task assigned to this queue has finished, this will return true and
544 /// fill in `outcome` with the details of the task. If no task in the queue has
545 /// finished, this function will return false. This function does not block.
546 ///
547 /// If a task has completed, this function will free its resources and the task
548 /// pointer will no longer be valid. The task will be removed from the queue.
549 ///
550 /// It is safe for multiple threads to call this function on the same queue at
551 /// once; a completed task will only go to one of the threads.
552 ///
553 /// ## Parameters
554 /// - `queue`: the async I/O task queue to query.
555 /// - `outcome`: details of a finished task will be written here. May not be
556 /// NULL.
557 ///
558 /// ## Return value
559 /// Returns true if a task has completed, false otherwise.
560 ///
561 /// ## Thread safety
562 /// It is safe to call this function from any thread.
563 ///
564 /// ## Availability
565 /// This function is available since SDL 3.2.0.
566 ///
567 /// ## See also
568 /// - [`SDL_WaitAsyncIOResult`]
569 pub fn SDL_GetAsyncIOResult(
570 queue: *mut SDL_AsyncIOQueue,
571 outcome: *mut SDL_AsyncIOOutcome,
572 ) -> ::core::primitive::bool;
573}
574
575unsafe extern "C" {
576 /// Block until an async I/O task queue has a completed task.
577 ///
578 /// This function puts the calling thread to sleep until there a task assigned
579 /// to the queue that has finished.
580 ///
581 /// If a task assigned to the queue has finished, this will return true and
582 /// fill in `outcome` with the details of the task. If no task in the queue has
583 /// finished, this function will return false.
584 ///
585 /// If a task has completed, this function will free its resources and the task
586 /// pointer will no longer be valid. The task will be removed from the queue.
587 ///
588 /// It is safe for multiple threads to call this function on the same queue at
589 /// once; a completed task will only go to one of the threads.
590 ///
591 /// Note that by the nature of various platforms, more than one waiting thread
592 /// may wake to handle a single task, but only one will obtain it, so
593 /// `timeoutMS` is a _maximum_ wait time, and this function may return false
594 /// sooner.
595 ///
596 /// This function may return false if there was a system error, the OS
597 /// inadvertently awoke multiple threads, or if [`SDL_SignalAsyncIOQueue()`] was
598 /// called to wake up all waiting threads without a finished task.
599 ///
600 /// A timeout can be used to specify a maximum wait time, but rather than
601 /// polling, it is possible to have a timeout of -1 to wait forever, and use
602 /// [`SDL_SignalAsyncIOQueue()`] to wake up the waiting threads later.
603 ///
604 /// ## Parameters
605 /// - `queue`: the async I/O task queue to wait on.
606 /// - `outcome`: details of a finished task will be written here. May not be
607 /// NULL.
608 /// - `timeoutMS`: the maximum time to wait, in milliseconds, or -1 to wait
609 /// indefinitely.
610 ///
611 /// ## Return value
612 /// Returns true if task has completed, false otherwise.
613 ///
614 /// ## Thread safety
615 /// It is safe to call this function from any thread.
616 ///
617 /// ## Availability
618 /// This function is available since SDL 3.2.0.
619 ///
620 /// ## See also
621 /// - [`SDL_SignalAsyncIOQueue`]
622 pub fn SDL_WaitAsyncIOResult(
623 queue: *mut SDL_AsyncIOQueue,
624 outcome: *mut SDL_AsyncIOOutcome,
625 timeoutMS: Sint32,
626 ) -> ::core::primitive::bool;
627}
628
629unsafe extern "C" {
630 /// Wake up any threads that are blocking in [`SDL_WaitAsyncIOResult()`].
631 ///
632 /// This will unblock any threads that are sleeping in a call to
633 /// [`SDL_WaitAsyncIOResult`] for the specified queue, and cause them to return
634 /// from that function.
635 ///
636 /// This can be useful when destroying a queue to make sure nothing is touching
637 /// it indefinitely. In this case, once this call completes, the caller should
638 /// take measures to make sure any previously-blocked threads have returned
639 /// from their wait and will not touch the queue again (perhaps by setting a
640 /// flag to tell the threads to terminate and then using [`SDL_WaitThread()`] to
641 /// make sure they've done so).
642 ///
643 /// ## Parameters
644 /// - `queue`: the async I/O task queue to signal.
645 ///
646 /// ## Thread safety
647 /// It is safe to call this function from any thread.
648 ///
649 /// ## Availability
650 /// This function is available since SDL 3.2.0.
651 ///
652 /// ## See also
653 /// - [`SDL_WaitAsyncIOResult`]
654 pub fn SDL_SignalAsyncIOQueue(queue: *mut SDL_AsyncIOQueue);
655}
656
657unsafe extern "C" {
658 /// Load all the data from a file path, asynchronously.
659 ///
660 /// This function returns as quickly as possible; it does not wait for the read
661 /// to complete. On a successful return, this work will continue in the
662 /// background. If the work begins, even failure is asynchronous: a failing
663 /// return value from this function only means the work couldn't start at all.
664 ///
665 /// The data is allocated with a zero byte at the end (null terminated) for
666 /// convenience. This extra byte is not included in SDL_AsyncIOOutcome's
667 /// bytes_transferred value.
668 ///
669 /// This function will allocate the buffer to contain the file. It must be
670 /// deallocated by calling [`SDL_free()`] on SDL_AsyncIOOutcome's buffer field
671 /// after completion.
672 ///
673 /// An [`SDL_AsyncIOQueue`] must be specified. The newly-created task will be added
674 /// to it when it completes its work.
675 ///
676 /// ## Parameters
677 /// - `file`: the path to read all available data from.
678 /// - `queue`: a queue to add the new [`SDL_AsyncIO`] to.
679 /// - `userdata`: an app-defined pointer that will be provided with the task
680 /// results.
681 ///
682 /// ## Return value
683 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
684 /// information.
685 ///
686 /// ## Availability
687 /// This function is available since SDL 3.2.0.
688 ///
689 /// ## See also
690 /// - [`SDL_LoadFile_IO`]
691 pub fn SDL_LoadFileAsync(
692 file: *const ::core::ffi::c_char,
693 queue: *mut SDL_AsyncIOQueue,
694 userdata: *mut ::core::ffi::c_void,
695 ) -> ::core::primitive::bool;
696}
697
698/// The asynchronous I/O operation structure.
699///
700/// This operates as an opaque handle. One can then request read or write
701/// operations on it.
702///
703/// ## Availability
704/// This struct is available since SDL 3.2.0.
705///
706/// ## See also
707/// - [`SDL_AsyncIOFromFile`]
708#[repr(C)]
709pub struct SDL_AsyncIO {
710 _opaque: [::core::primitive::u8; 0],
711}
712
713/// A queue of completed asynchronous I/O tasks.
714///
715/// When starting an asynchronous operation, you specify a queue for the new
716/// task. A queue can be asked later if any tasks in it have completed,
717/// allowing an app to manage multiple pending tasks in one place, in whatever
718/// order they complete.
719///
720/// ## Availability
721/// This struct is available since SDL 3.2.0.
722///
723/// ## See also
724/// - [`SDL_CreateAsyncIOQueue`]
725/// - [`SDL_ReadAsyncIO`]
726/// - [`SDL_WriteAsyncIO`]
727/// - [`SDL_GetAsyncIOResult`]
728/// - [`SDL_WaitAsyncIOResult`]
729#[repr(C)]
730pub struct SDL_AsyncIOQueue {
731 _opaque: [::core::primitive::u8; 0],
732}
733
734#[cfg(doc)]
735use crate::everything::*;