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