| 1 | /* | 
| 2 |   Simple DirectMedia Layer | 
| 3 |   Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | 
| 4 |  | 
| 5 |   This software is provided 'as-is', without any express or implied | 
| 6 |   warranty.  In no event will the authors be held liable for any damages | 
| 7 |   arising from the use of this software. | 
| 8 |  | 
| 9 |   Permission is granted to anyone to use this software for any purpose, | 
| 10 |   including commercial applications, and to alter it and redistribute it | 
| 11 |   freely, subject to the following restrictions: | 
| 12 |  | 
| 13 |   1. The origin of this software must not be misrepresented; you must not | 
| 14 |      claim that you wrote the original software. If you use this software | 
| 15 |      in a product, an acknowledgment in the product documentation would be | 
| 16 |      appreciated but is not required. | 
| 17 |   2. Altered source versions must be plainly marked as such, and must not be | 
| 18 |      misrepresented as being the original software. | 
| 19 |   3. This notice may not be removed or altered from any source distribution. | 
| 20 | */ | 
| 21 |  | 
| 22 | /* WIKI CATEGORY: AsyncIO */ | 
| 23 |  | 
| 24 | /** | 
| 25 |  * # CategoryAsyncIO | 
| 26 |  * | 
| 27 |  * SDL offers a way to perform I/O asynchronously. This allows an app to read | 
| 28 |  * or write files without waiting for data to actually transfer; the functions | 
| 29 |  * that request I/O never block while the request is fulfilled. | 
| 30 |  * | 
| 31 |  * Instead, the data moves in the background and the app can check for results | 
| 32 |  * at their leisure. | 
| 33 |  * | 
| 34 |  * This is more complicated than just reading and writing files in a | 
| 35 |  * synchronous way, but it can allow for more efficiency, and never having | 
| 36 |  * framerate drops as the hard drive catches up, etc. | 
| 37 |  * | 
| 38 |  * The general usage pattern for async I/O is: | 
| 39 |  * | 
| 40 |  * - Create one or more SDL_AsyncIOQueue objects. | 
| 41 |  * - Open files with SDL_AsyncIOFromFile. | 
| 42 |  * - Start I/O tasks to the files with SDL_ReadAsyncIO or SDL_WriteAsyncIO, | 
| 43 |  *   putting those tasks into one of the queues. | 
| 44 |  * - Later on, use SDL_GetAsyncIOResult on a queue to see if any task is | 
| 45 |  *   finished without blocking. Tasks might finish in any order with success | 
| 46 |  *   or failure. | 
| 47 |  * - When all your tasks are done, close the file with SDL_CloseAsyncIO. This | 
| 48 |  *   also generates a task, since it might flush data to disk! | 
| 49 |  * | 
| 50 |  * This all works, without blocking, in a single thread, but one can also wait | 
| 51 |  * on a queue in a background thread, sleeping until new results have arrived: | 
| 52 |  * | 
| 53 |  * - Call SDL_WaitAsyncIOResult from one or more threads to efficiently block | 
| 54 |  *   until new tasks complete. | 
| 55 |  * - When shutting down, call SDL_SignalAsyncIOQueue to unblock any sleeping | 
| 56 |  *   threads despite there being no new tasks completed. | 
| 57 |  * | 
| 58 |  * And, of course, to match the synchronous SDL_LoadFile, we offer | 
| 59 |  * SDL_LoadFileAsync as a convenience function. This will handle allocating a | 
| 60 |  * buffer, slurping in the file data, and null-terminating it; you still check | 
| 61 |  * for results later. | 
| 62 |  * | 
| 63 |  * Behind the scenes, SDL will use newer, efficient APIs on platforms that | 
| 64 |  * support them: Linux's io_uring and Windows 11's IoRing, for example. If | 
| 65 |  * those technologies aren't available, SDL will offload the work to a thread | 
| 66 |  * pool that will manage otherwise-synchronous loads without blocking the app. | 
| 67 |  * | 
| 68 |  * ## Best Practices | 
| 69 |  * | 
| 70 |  * Simple non-blocking I/O--for an app that just wants to pick up data | 
| 71 |  * whenever it's ready without losing framerate waiting on disks to spin--can | 
| 72 |  * use whatever pattern works well for the program. In this case, simply call | 
| 73 |  * SDL_ReadAsyncIO, or maybe SDL_LoadFileAsync, as needed. Once a frame, call | 
| 74 |  * SDL_GetAsyncIOResult to check for any completed tasks and deal with the | 
| 75 |  * data as it arrives. | 
| 76 |  * | 
| 77 |  * If two separate pieces of the same program need their own I/O, it is legal | 
| 78 |  * for each to create their own queue. This will prevent either piece from | 
| 79 |  * accidentally consuming the other's completed tasks. Each queue does require | 
| 80 |  * some amount of resources, but it is not an overwhelming cost. Do not make a | 
| 81 |  * queue for each task, however. It is better to put many tasks into a single | 
| 82 |  * queue. They will be reported in order of completion, not in the order they | 
| 83 |  * were submitted, so it doesn't generally matter what order tasks are | 
| 84 |  * started. | 
| 85 |  * | 
| 86 |  * One async I/O queue can be shared by multiple threads, or one thread can | 
| 87 |  * have more than one queue, but the most efficient way--if ruthless | 
| 88 |  * efficiency is the goal--is to have one queue per thread, with multiple | 
| 89 |  * threads working in parallel, and attempt to keep each queue loaded with | 
| 90 |  * tasks that are both started by and consumed by the same thread. On modern | 
| 91 |  * platforms that can use newer interfaces, this can keep data flowing as | 
| 92 |  * efficiently as possible all the way from storage hardware to the app, with | 
| 93 |  * no contention between threads for access to the same queue. | 
| 94 |  * | 
| 95 |  * Written data is not guaranteed to make it to physical media by the time a | 
| 96 |  * closing task is completed, unless SDL_CloseAsyncIO is called with its | 
| 97 |  * `flush` parameter set to true, which is to say that a successful result | 
| 98 |  * here can still result in lost data during an unfortunately-timed power | 
| 99 |  * outage if not flushed. However, flushing will take longer and may be | 
| 100 |  * unnecessary, depending on the app's needs. | 
| 101 |  */ | 
| 102 |  | 
| 103 | #ifndef SDL_asyncio_h_ | 
| 104 | #define SDL_asyncio_h_ | 
| 105 |  | 
| 106 | #include <SDL3/SDL_stdinc.h> | 
| 107 |  | 
| 108 | #include <SDL3/SDL_begin_code.h> | 
| 109 | /* Set up for C function definitions, even when using C++ */ | 
| 110 | #ifdef __cplusplus | 
| 111 | extern "C"  { | 
| 112 | #endif | 
| 113 |  | 
| 114 | /** | 
| 115 |  * The asynchronous I/O operation structure. | 
| 116 |  * | 
| 117 |  * This operates as an opaque handle. One can then request read or write | 
| 118 |  * operations on it. | 
| 119 |  * | 
| 120 |  * \since This struct is available since SDL 3.2.0. | 
| 121 |  * | 
| 122 |  * \sa SDL_AsyncIOFromFile | 
| 123 |  */ | 
| 124 | typedef struct SDL_AsyncIO SDL_AsyncIO; | 
| 125 |  | 
| 126 | /** | 
| 127 |  * Types of asynchronous I/O tasks. | 
| 128 |  * | 
| 129 |  * \since This enum is available since SDL 3.2.0. | 
| 130 |  */ | 
| 131 | typedef enum SDL_AsyncIOTaskType | 
| 132 | { | 
| 133 |     SDL_ASYNCIO_TASK_READ,   /**< A read operation. */ | 
| 134 |     SDL_ASYNCIO_TASK_WRITE,  /**< A write operation. */ | 
| 135 |     SDL_ASYNCIO_TASK_CLOSE   /**< A close operation. */ | 
| 136 | } SDL_AsyncIOTaskType; | 
| 137 |  | 
| 138 | /** | 
| 139 |  * Possible outcomes of an asynchronous I/O task. | 
| 140 |  * | 
| 141 |  * \since This enum is available since SDL 3.2.0. | 
| 142 |  */ | 
| 143 | typedef enum SDL_AsyncIOResult | 
| 144 | { | 
| 145 |     SDL_ASYNCIO_COMPLETE,  /**< request was completed without error */ | 
| 146 |     SDL_ASYNCIO_FAILURE,   /**< request failed for some reason; check SDL_GetError()! */ | 
| 147 |     SDL_ASYNCIO_CANCELED   /**< request was canceled before completing. */ | 
| 148 | } SDL_AsyncIOResult; | 
| 149 |  | 
| 150 | /** | 
| 151 |  * Information about a completed asynchronous I/O request. | 
| 152 |  * | 
| 153 |  * \since This struct is available since SDL 3.2.0. | 
| 154 |  */ | 
| 155 | typedef struct SDL_AsyncIOOutcome | 
| 156 | { | 
| 157 |     SDL_AsyncIO *asyncio;   /**< what generated this task. This pointer will be invalid if it was closed! */ | 
| 158 |     SDL_AsyncIOTaskType type;  /**< What sort of task was this? Read, write, etc? */ | 
| 159 |     SDL_AsyncIOResult result;  /**< the result of the work (success, failure, cancellation). */ | 
| 160 |     void *buffer;  /**< buffer where data was read/written. */ | 
| 161 |     Uint64 offset;  /**< offset in the SDL_AsyncIO where data was read/written. */ | 
| 162 |     Uint64 bytes_requested;  /**< number of bytes the task was to read/write. */ | 
| 163 |     Uint64 bytes_transferred;  /**< actual number of bytes that were read/written. */ | 
| 164 |     void *userdata;    /**< pointer provided by the app when starting the task */ | 
| 165 | } SDL_AsyncIOOutcome; | 
| 166 |  | 
| 167 | /** | 
| 168 |  * A queue of completed asynchronous I/O tasks. | 
| 169 |  * | 
| 170 |  * When starting an asynchronous operation, you specify a queue for the new | 
| 171 |  * task. A queue can be asked later if any tasks in it have completed, | 
| 172 |  * allowing an app to manage multiple pending tasks in one place, in whatever | 
| 173 |  * order they complete. | 
| 174 |  * | 
| 175 |  * \since This struct is available since SDL 3.2.0. | 
| 176 |  * | 
| 177 |  * \sa SDL_CreateAsyncIOQueue | 
| 178 |  * \sa SDL_ReadAsyncIO | 
| 179 |  * \sa SDL_WriteAsyncIO | 
| 180 |  * \sa SDL_GetAsyncIOResult | 
| 181 |  * \sa SDL_WaitAsyncIOResult | 
| 182 |  */ | 
| 183 | typedef struct SDL_AsyncIOQueue SDL_AsyncIOQueue; | 
| 184 |  | 
| 185 | /** | 
| 186 |  * Use this function to create a new SDL_AsyncIO object for reading from | 
| 187 |  * and/or writing to a named file. | 
| 188 |  * | 
| 189 |  * The `mode` string understands the following values: | 
| 190 |  * | 
| 191 |  * - "r": Open a file for reading only. It must exist. | 
| 192 |  * - "w": Open a file for writing only. It will create missing files or | 
| 193 |  *   truncate existing ones. | 
| 194 |  * - "r+": Open a file for update both reading and writing. The file must | 
| 195 |  *   exist. | 
| 196 |  * - "w+": Create an empty file for both reading and writing. If a file with | 
| 197 |  *   the same name already exists its content is erased and the file is | 
| 198 |  *   treated as a new empty file. | 
| 199 |  * | 
| 200 |  * There is no "b" mode, as there is only "binary" style I/O, and no "a" mode | 
| 201 |  * for appending, since you specify the position when starting a task. | 
| 202 |  * | 
| 203 |  * This function supports Unicode filenames, but they must be encoded in UTF-8 | 
| 204 |  * format, regardless of the underlying operating system. | 
| 205 |  * | 
| 206 |  * This call is _not_ asynchronous; it will open the file before returning, | 
| 207 |  * under the assumption that doing so is generally a fast operation. Future | 
| 208 |  * reads and writes to the opened file will be async, however. | 
| 209 |  * | 
| 210 |  * \param file a UTF-8 string representing the filename to open. | 
| 211 |  * \param mode an ASCII string representing the mode to be used for opening | 
| 212 |  *             the file. | 
| 213 |  * \returns a pointer to the SDL_AsyncIO structure that is created or NULL on | 
| 214 |  *          failure; call SDL_GetError() for more information. | 
| 215 |  * | 
| 216 |  * \since This function is available since SDL 3.2.0. | 
| 217 |  * | 
| 218 |  * \sa SDL_CloseAsyncIO | 
| 219 |  * \sa SDL_ReadAsyncIO | 
| 220 |  * \sa SDL_WriteAsyncIO | 
| 221 |  */ | 
| 222 | extern SDL_DECLSPEC SDL_AsyncIO * SDLCALL SDL_AsyncIOFromFile(const char *file, const char *mode); | 
| 223 |  | 
| 224 | /** | 
| 225 |  * Use this function to get the size of the data stream in an SDL_AsyncIO. | 
| 226 |  * | 
| 227 |  * This call is _not_ asynchronous; it assumes that obtaining this info is a | 
| 228 |  * non-blocking operation in most reasonable cases. | 
| 229 |  * | 
| 230 |  * \param asyncio the SDL_AsyncIO to get the size of the data stream from. | 
| 231 |  * \returns the size of the data stream in the SDL_IOStream on success or a | 
| 232 |  *          negative error code on failure; call SDL_GetError() for more | 
| 233 |  *          information. | 
| 234 |  * | 
| 235 |  * \threadsafety It is safe to call this function from any thread. | 
| 236 |  * | 
| 237 |  * \since This function is available since SDL 3.2.0. | 
| 238 |  */ | 
| 239 | extern SDL_DECLSPEC Sint64 SDLCALL SDL_GetAsyncIOSize(SDL_AsyncIO *asyncio); | 
| 240 |  | 
| 241 | /** | 
| 242 |  * Start an async read. | 
| 243 |  * | 
| 244 |  * This function reads up to `size` bytes from `offset` position in the data | 
| 245 |  * source to the area pointed at by `ptr`. This function may read less bytes | 
| 246 |  * than requested. | 
| 247 |  * | 
| 248 |  * This function returns as quickly as possible; it does not wait for the read | 
| 249 |  * to complete. On a successful return, this work will continue in the | 
| 250 |  * background. If the work begins, even failure is asynchronous: a failing | 
| 251 |  * return value from this function only means the work couldn't start at all. | 
| 252 |  * | 
| 253 |  * `ptr` must remain available until the work is done, and may be accessed by | 
| 254 |  * the system at any time until then. Do not allocate it on the stack, as this | 
| 255 |  * might take longer than the life of the calling function to complete! | 
| 256 |  * | 
| 257 |  * An SDL_AsyncIOQueue must be specified. The newly-created task will be added | 
| 258 |  * to it when it completes its work. | 
| 259 |  * | 
| 260 |  * \param asyncio a pointer to an SDL_AsyncIO structure. | 
| 261 |  * \param ptr a pointer to a buffer to read data into. | 
| 262 |  * \param offset the position to start reading in the data source. | 
| 263 |  * \param size the number of bytes to read from the data source. | 
| 264 |  * \param queue a queue to add the new SDL_AsyncIO to. | 
| 265 |  * \param userdata an app-defined pointer that will be provided with the task | 
| 266 |  *                 results. | 
| 267 |  * \returns true on success or false on failure; call SDL_GetError() for more | 
| 268 |  *          information. | 
| 269 |  * | 
| 270 |  * \threadsafety It is safe to call this function from any thread. | 
| 271 |  * | 
| 272 |  * \since This function is available since SDL 3.2.0. | 
| 273 |  * | 
| 274 |  * \sa SDL_WriteAsyncIO | 
| 275 |  * \sa SDL_CreateAsyncIOQueue | 
| 276 |  */ | 
| 277 | extern SDL_DECLSPEC bool SDLCALL SDL_ReadAsyncIO(SDL_AsyncIO *asyncio, void *ptr, Uint64 offset, Uint64 size, SDL_AsyncIOQueue *queue, void *userdata); | 
| 278 |  | 
| 279 | /** | 
| 280 |  * Start an async write. | 
| 281 |  * | 
| 282 |  * This function writes `size` bytes from `offset` position in the data source | 
| 283 |  * to the area pointed at by `ptr`. | 
| 284 |  * | 
| 285 |  * This function returns as quickly as possible; it does not wait for the | 
| 286 |  * write to complete. On a successful return, this work will continue in the | 
| 287 |  * background. If the work begins, even failure is asynchronous: a failing | 
| 288 |  * return value from this function only means the work couldn't start at all. | 
| 289 |  * | 
| 290 |  * `ptr` must remain available until the work is done, and may be accessed by | 
| 291 |  * the system at any time until then. Do not allocate it on the stack, as this | 
| 292 |  * might take longer than the life of the calling function to complete! | 
| 293 |  * | 
| 294 |  * An SDL_AsyncIOQueue must be specified. The newly-created task will be added | 
| 295 |  * to it when it completes its work. | 
| 296 |  * | 
| 297 |  * \param asyncio a pointer to an SDL_AsyncIO structure. | 
| 298 |  * \param ptr a pointer to a buffer to write data from. | 
| 299 |  * \param offset the position to start writing to the data source. | 
| 300 |  * \param size the number of bytes to write to the data source. | 
| 301 |  * \param queue a queue to add the new SDL_AsyncIO to. | 
| 302 |  * \param userdata an app-defined pointer that will be provided with the task | 
| 303 |  *                 results. | 
| 304 |  * \returns true on success or false on failure; call SDL_GetError() for more | 
| 305 |  *          information. | 
| 306 |  * | 
| 307 |  * \threadsafety It is safe to call this function from any thread. | 
| 308 |  * | 
| 309 |  * \since This function is available since SDL 3.2.0. | 
| 310 |  * | 
| 311 |  * \sa SDL_ReadAsyncIO | 
| 312 |  * \sa SDL_CreateAsyncIOQueue | 
| 313 |  */ | 
| 314 | extern SDL_DECLSPEC bool SDLCALL SDL_WriteAsyncIO(SDL_AsyncIO *asyncio, void *ptr, Uint64 offset, Uint64 size, SDL_AsyncIOQueue *queue, void *userdata); | 
| 315 |  | 
| 316 | /** | 
| 317 |  * Close and free any allocated resources for an async I/O object. | 
| 318 |  * | 
| 319 |  * Closing a file is _also_ an asynchronous task! If a write failure were to | 
| 320 |  * happen during the closing process, for example, the task results will | 
| 321 |  * report it as usual. | 
| 322 |  * | 
| 323 |  * Closing a file that has been written to does not guarantee the data has | 
| 324 |  * made it to physical media; it may remain in the operating system's file | 
| 325 |  * cache, for later writing to disk. This means that a successfully-closed | 
| 326 |  * file can be lost if the system crashes or loses power in this small window. | 
| 327 |  * To prevent this, call this function with the `flush` parameter set to true. | 
| 328 |  * This will make the operation take longer, and perhaps increase system load | 
| 329 |  * in general, but a successful result guarantees that the data has made it to | 
| 330 |  * physical storage. Don't use this for temporary files, caches, and | 
| 331 |  * unimportant data, and definitely use it for crucial irreplaceable files, | 
| 332 |  * like game saves. | 
| 333 |  * | 
| 334 |  * This function guarantees that the close will happen after any other pending | 
| 335 |  * tasks to `asyncio`, so it's safe to open a file, start several operations, | 
| 336 |  * close the file immediately, then check for all results later. This function | 
| 337 |  * will not block until the tasks have completed. | 
| 338 |  * | 
| 339 |  * Once this function returns true, `asyncio` is no longer valid, regardless | 
| 340 |  * of any future outcomes. Any completed tasks might still contain this | 
| 341 |  * pointer in their SDL_AsyncIOOutcome data, in case the app was using this | 
| 342 |  * value to track information, but it should not be used again. | 
| 343 |  * | 
| 344 |  * If this function returns false, the close wasn't started at all, and it's | 
| 345 |  * safe to attempt to close again later. | 
| 346 |  * | 
| 347 |  * An SDL_AsyncIOQueue must be specified. The newly-created task will be added | 
| 348 |  * to it when it completes its work. | 
| 349 |  * | 
| 350 |  * \param asyncio a pointer to an SDL_AsyncIO structure to close. | 
| 351 |  * \param flush true if data should sync to disk before the task completes. | 
| 352 |  * \param queue a queue to add the new SDL_AsyncIO to. | 
| 353 |  * \param userdata an app-defined pointer that will be provided with the task | 
| 354 |  *                 results. | 
| 355 |  * \returns true on success or false on failure; call SDL_GetError() for more | 
| 356 |  *          information. | 
| 357 |  * | 
| 358 |  * \threadsafety It is safe to call this function from any thread, but two | 
| 359 |  *               threads should not attempt to close the same object. | 
| 360 |  * | 
| 361 |  * \since This function is available since SDL 3.2.0. | 
| 362 |  */ | 
| 363 | extern SDL_DECLSPEC bool SDLCALL SDL_CloseAsyncIO(SDL_AsyncIO *asyncio, bool flush, SDL_AsyncIOQueue *queue, void *userdata); | 
| 364 |  | 
| 365 | /** | 
| 366 |  * Create a task queue for tracking multiple I/O operations. | 
| 367 |  * | 
| 368 |  * Async I/O operations are assigned to a queue when started. The queue can be | 
| 369 |  * checked for completed tasks thereafter. | 
| 370 |  * | 
| 371 |  * \returns a new task queue object or NULL if there was an error; call | 
| 372 |  *          SDL_GetError() for more information. | 
| 373 |  * | 
| 374 |  * \threadsafety It is safe to call this function from any thread. | 
| 375 |  * | 
| 376 |  * \since This function is available since SDL 3.2.0. | 
| 377 |  * | 
| 378 |  * \sa SDL_DestroyAsyncIOQueue | 
| 379 |  * \sa SDL_GetAsyncIOResult | 
| 380 |  * \sa SDL_WaitAsyncIOResult | 
| 381 |  */ | 
| 382 | extern SDL_DECLSPEC SDL_AsyncIOQueue * SDLCALL SDL_CreateAsyncIOQueue(void); | 
| 383 |  | 
| 384 | /** | 
| 385 |  * Destroy a previously-created async I/O task queue. | 
| 386 |  * | 
| 387 |  * If there are still tasks pending for this queue, this call will block until | 
| 388 |  * those tasks are finished. All those tasks will be deallocated. Their | 
| 389 |  * results will be lost to the app. | 
| 390 |  * | 
| 391 |  * Any pending reads from SDL_LoadFileAsync() that are still in this queue | 
| 392 |  * will have their buffers deallocated by this function, to prevent a memory | 
| 393 |  * leak. | 
| 394 |  * | 
| 395 |  * Once this function is called, the queue is no longer valid and should not | 
| 396 |  * be used, including by other threads that might access it while destruction | 
| 397 |  * is blocking on pending tasks. | 
| 398 |  * | 
| 399 |  * Do not destroy a queue that still has threads waiting on it through | 
| 400 |  * SDL_WaitAsyncIOResult(). You can call SDL_SignalAsyncIOQueue() first to | 
| 401 |  * unblock those threads, and take measures (such as SDL_WaitThread()) to make | 
| 402 |  * sure they have finished their wait and won't wait on the queue again. | 
| 403 |  * | 
| 404 |  * \param queue the task queue to destroy. | 
| 405 |  * | 
| 406 |  * \threadsafety It is safe to call this function from any thread, so long as | 
| 407 |  *               no other thread is waiting on the queue with | 
| 408 |  *               SDL_WaitAsyncIOResult. | 
| 409 |  * | 
| 410 |  * \since This function is available since SDL 3.2.0. | 
| 411 |  */ | 
| 412 | extern SDL_DECLSPEC void SDLCALL SDL_DestroyAsyncIOQueue(SDL_AsyncIOQueue *queue); | 
| 413 |  | 
| 414 | /** | 
| 415 |  * Query an async I/O task queue for completed tasks. | 
| 416 |  * | 
| 417 |  * If a task assigned to this queue has finished, this will return true and | 
| 418 |  * fill in `outcome` with the details of the task. If no task in the queue has | 
| 419 |  * finished, this function will return false. This function does not block. | 
| 420 |  * | 
| 421 |  * If a task has completed, this function will free its resources and the task | 
| 422 |  * pointer will no longer be valid. The task will be removed from the queue. | 
| 423 |  * | 
| 424 |  * It is safe for multiple threads to call this function on the same queue at | 
| 425 |  * once; a completed task will only go to one of the threads. | 
| 426 |  * | 
| 427 |  * \param queue the async I/O task queue to query. | 
| 428 |  * \param outcome details of a finished task will be written here. May not be | 
| 429 |  *                NULL. | 
| 430 |  * \returns true if a task has completed, false otherwise. | 
| 431 |  * | 
| 432 |  * \threadsafety It is safe to call this function from any thread. | 
| 433 |  * | 
| 434 |  * \since This function is available since SDL 3.2.0. | 
| 435 |  * | 
| 436 |  * \sa SDL_WaitAsyncIOResult | 
| 437 |  */ | 
| 438 | extern SDL_DECLSPEC bool SDLCALL SDL_GetAsyncIOResult(SDL_AsyncIOQueue *queue, SDL_AsyncIOOutcome *outcome); | 
| 439 |  | 
| 440 | /** | 
| 441 |  * Block until an async I/O task queue has a completed task. | 
| 442 |  * | 
| 443 |  * This function puts the calling thread to sleep until there a task assigned | 
| 444 |  * to the queue that has finished. | 
| 445 |  * | 
| 446 |  * If a task assigned to the queue has finished, this will return true and | 
| 447 |  * fill in `outcome` with the details of the task. If no task in the queue has | 
| 448 |  * finished, this function will return false. | 
| 449 |  * | 
| 450 |  * If a task has completed, this function will free its resources and the task | 
| 451 |  * pointer will no longer be valid. The task will be removed from the queue. | 
| 452 |  * | 
| 453 |  * It is safe for multiple threads to call this function on the same queue at | 
| 454 |  * once; a completed task will only go to one of the threads. | 
| 455 |  * | 
| 456 |  * Note that by the nature of various platforms, more than one waiting thread | 
| 457 |  * may wake to handle a single task, but only one will obtain it, so | 
| 458 |  * `timeoutMS` is a _maximum_ wait time, and this function may return false | 
| 459 |  * sooner. | 
| 460 |  * | 
| 461 |  * This function may return false if there was a system error, the OS | 
| 462 |  * inadvertently awoke multiple threads, or if SDL_SignalAsyncIOQueue() was | 
| 463 |  * called to wake up all waiting threads without a finished task. | 
| 464 |  * | 
| 465 |  * A timeout can be used to specify a maximum wait time, but rather than | 
| 466 |  * polling, it is possible to have a timeout of -1 to wait forever, and use | 
| 467 |  * SDL_SignalAsyncIOQueue() to wake up the waiting threads later. | 
| 468 |  * | 
| 469 |  * \param queue the async I/O task queue to wait on. | 
| 470 |  * \param outcome details of a finished task will be written here. May not be | 
| 471 |  *                NULL. | 
| 472 |  * \param timeoutMS the maximum time to wait, in milliseconds, or -1 to wait | 
| 473 |  *                  indefinitely. | 
| 474 |  * \returns true if task has completed, false otherwise. | 
| 475 |  * | 
| 476 |  * \threadsafety It is safe to call this function from any thread. | 
| 477 |  * | 
| 478 |  * \since This function is available since SDL 3.2.0. | 
| 479 |  * | 
| 480 |  * \sa SDL_SignalAsyncIOQueue | 
| 481 |  */ | 
| 482 | extern SDL_DECLSPEC bool SDLCALL SDL_WaitAsyncIOResult(SDL_AsyncIOQueue *queue, SDL_AsyncIOOutcome *outcome, Sint32 timeoutMS); | 
| 483 |  | 
| 484 | /** | 
| 485 |  * Wake up any threads that are blocking in SDL_WaitAsyncIOResult(). | 
| 486 |  * | 
| 487 |  * This will unblock any threads that are sleeping in a call to | 
| 488 |  * SDL_WaitAsyncIOResult for the specified queue, and cause them to return | 
| 489 |  * from that function. | 
| 490 |  * | 
| 491 |  * This can be useful when destroying a queue to make sure nothing is touching | 
| 492 |  * it indefinitely. In this case, once this call completes, the caller should | 
| 493 |  * take measures to make sure any previously-blocked threads have returned | 
| 494 |  * from their wait and will not touch the queue again (perhaps by setting a | 
| 495 |  * flag to tell the threads to terminate and then using SDL_WaitThread() to | 
| 496 |  * make sure they've done so). | 
| 497 |  * | 
| 498 |  * \param queue the async I/O task queue to signal. | 
| 499 |  * | 
| 500 |  * \threadsafety It is safe to call this function from any thread. | 
| 501 |  * | 
| 502 |  * \since This function is available since SDL 3.2.0. | 
| 503 |  * | 
| 504 |  * \sa SDL_WaitAsyncIOResult | 
| 505 |  */ | 
| 506 | extern SDL_DECLSPEC void SDLCALL SDL_SignalAsyncIOQueue(SDL_AsyncIOQueue *queue); | 
| 507 |  | 
| 508 | /** | 
| 509 |  * Load all the data from a file path, asynchronously. | 
| 510 |  * | 
| 511 |  * This function returns as quickly as possible; it does not wait for the read | 
| 512 |  * to complete. On a successful return, this work will continue in the | 
| 513 |  * background. If the work begins, even failure is asynchronous: a failing | 
| 514 |  * return value from this function only means the work couldn't start at all. | 
| 515 |  * | 
| 516 |  * The data is allocated with a zero byte at the end (null terminated) for | 
| 517 |  * convenience. This extra byte is not included in SDL_AsyncIOOutcome's | 
| 518 |  * bytes_transferred value. | 
| 519 |  * | 
| 520 |  * This function will allocate the buffer to contain the file. It must be | 
| 521 |  * deallocated by calling SDL_free() on SDL_AsyncIOOutcome's buffer field | 
| 522 |  * after completion. | 
| 523 |  * | 
| 524 |  * An SDL_AsyncIOQueue must be specified. The newly-created task will be added | 
| 525 |  * to it when it completes its work. | 
| 526 |  * | 
| 527 |  * \param file the path to read all available data from. | 
| 528 |  * \param queue a queue to add the new SDL_AsyncIO to. | 
| 529 |  * \param userdata an app-defined pointer that will be provided with the task | 
| 530 |  *                 results. | 
| 531 |  * \returns true on success or false on failure; call SDL_GetError() for more | 
| 532 |  *          information. | 
| 533 |  * | 
| 534 |  * \since This function is available since SDL 3.2.0. | 
| 535 |  * | 
| 536 |  * \sa SDL_LoadFile_IO | 
| 537 |  */ | 
| 538 | extern SDL_DECLSPEC bool SDLCALL SDL_LoadFileAsync(const char *file, SDL_AsyncIOQueue *queue, void *userdata); | 
| 539 |  | 
| 540 | /* Ends C function definitions when using C++ */ | 
| 541 | #ifdef __cplusplus | 
| 542 | } | 
| 543 | #endif | 
| 544 | #include <SDL3/SDL_close_code.h> | 
| 545 |  | 
| 546 | #endif /* SDL_asyncio_h_ */ | 
| 547 |  |