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 | |