sdl3_sys/generated/thread.rs
1//! SDL offers cross-platform thread management functions. These are mostly
2//! concerned with starting threads, setting their priority, and dealing with
3//! their termination.
4//!
5//! In addition, there is support for Thread Local Storage (data that is unique
6//! to each thread, but accessed from a single key).
7//!
8//! On platforms without thread support (such as Emscripten when built without
9//! pthreads), these functions still exist, but things like [`SDL_CreateThread()`]
10//! will report failure without doing anything.
11//!
12//! If you're going to work with threads, you almost certainly need to have a
13//! good understanding of thread safety measures: locking and synchronization
14//! mechanisms are handled by the functions in SDL_mutex.h.
15
16use super::stdinc::*;
17
18use super::error::*;
19
20use super::properties::*;
21
22use super::atomic::*;
23
24apply_cfg!(#[cfg(any(doc, windows))] => {
25});
26
27/// A unique numeric ID that identifies a thread.
28///
29/// These are different from [`SDL_Thread`] objects, which are generally what an
30/// application will operate on, but having a way to uniquely identify a thread
31/// can be useful at times.
32///
33/// ## Availability
34/// This datatype is available since SDL 3.2.0.
35///
36/// ## See also
37/// - [`SDL_GetThreadID`]
38/// - [`SDL_GetCurrentThreadID`]
39#[repr(transparent)]
40#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
41#[cfg_attr(feature = "debug-impls", derive(Debug))]
42pub struct SDL_ThreadID(pub Uint64);
43
44impl ::core::cmp::PartialEq<Uint64> for SDL_ThreadID {
45 #[inline(always)]
46 fn eq(&self, other: &Uint64) -> bool {
47 &self.0 == other
48 }
49}
50
51impl ::core::cmp::PartialEq<SDL_ThreadID> for Uint64 {
52 #[inline(always)]
53 fn eq(&self, other: &SDL_ThreadID) -> bool {
54 self == &other.0
55 }
56}
57
58impl From<SDL_ThreadID> for Uint64 {
59 #[inline(always)]
60 fn from(value: SDL_ThreadID) -> Self {
61 value.0
62 }
63}
64
65#[cfg(feature = "metadata")]
66impl sdl3_sys::metadata::GroupMetadata for SDL_ThreadID {
67 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
68 &crate::metadata::thread::METADATA_SDL_ThreadID;
69}
70
71/// Thread local storage ID.
72///
73/// 0 is the invalid ID. An app can create these and then set data for these
74/// IDs that is unique to each thread.
75///
76/// ## Availability
77/// This datatype is available since SDL 3.2.0.
78///
79/// ## See also
80/// - [`SDL_GetTLS`]
81/// - [`SDL_SetTLS`]
82#[repr(transparent)]
83#[derive(Default)]
84#[cfg_attr(feature = "debug-impls", derive(Debug))]
85pub struct SDL_TLSID(pub SDL_AtomicInt);
86
87impl From<SDL_TLSID> for SDL_AtomicInt {
88 #[inline(always)]
89 fn from(value: SDL_TLSID) -> Self {
90 value.0
91 }
92}
93
94#[cfg(feature = "metadata")]
95impl sdl3_sys::metadata::GroupMetadata for SDL_TLSID {
96 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
97 &crate::metadata::thread::METADATA_SDL_TLSID;
98}
99
100/// The SDL thread priority.
101///
102/// SDL will make system changes as necessary in order to apply the thread
103/// priority. Code which attempts to control thread state related to priority
104/// should be aware that calling [`SDL_SetCurrentThreadPriority`] may alter such
105/// state. [`SDL_HINT_THREAD_PRIORITY_POLICY`] can be used to control aspects of
106/// this behavior.
107///
108/// ## Availability
109/// This enum is available since SDL 3.2.0.
110///
111/// ## Known values (`sdl3-sys`)
112/// | Associated constant | Global constant | Description |
113/// | ------------------- | --------------- | ----------- |
114/// | [`LOW`](SDL_ThreadPriority::LOW) | [`SDL_THREAD_PRIORITY_LOW`] | |
115/// | [`NORMAL`](SDL_ThreadPriority::NORMAL) | [`SDL_THREAD_PRIORITY_NORMAL`] | |
116/// | [`HIGH`](SDL_ThreadPriority::HIGH) | [`SDL_THREAD_PRIORITY_HIGH`] | |
117/// | [`TIME_CRITICAL`](SDL_ThreadPriority::TIME_CRITICAL) | [`SDL_THREAD_PRIORITY_TIME_CRITICAL`] | |
118#[repr(transparent)]
119#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
120pub struct SDL_ThreadPriority(pub ::core::ffi::c_int);
121
122impl ::core::cmp::PartialEq<::core::ffi::c_int> for SDL_ThreadPriority {
123 #[inline(always)]
124 fn eq(&self, other: &::core::ffi::c_int) -> bool {
125 &self.0 == other
126 }
127}
128
129impl ::core::cmp::PartialEq<SDL_ThreadPriority> for ::core::ffi::c_int {
130 #[inline(always)]
131 fn eq(&self, other: &SDL_ThreadPriority) -> bool {
132 self == &other.0
133 }
134}
135
136impl From<SDL_ThreadPriority> for ::core::ffi::c_int {
137 #[inline(always)]
138 fn from(value: SDL_ThreadPriority) -> Self {
139 value.0
140 }
141}
142
143#[cfg(feature = "debug-impls")]
144impl ::core::fmt::Debug for SDL_ThreadPriority {
145 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
146 #[allow(unreachable_patterns)]
147 f.write_str(match *self {
148 Self::LOW => "SDL_THREAD_PRIORITY_LOW",
149 Self::NORMAL => "SDL_THREAD_PRIORITY_NORMAL",
150 Self::HIGH => "SDL_THREAD_PRIORITY_HIGH",
151 Self::TIME_CRITICAL => "SDL_THREAD_PRIORITY_TIME_CRITICAL",
152
153 _ => return write!(f, "SDL_ThreadPriority({})", self.0),
154 })
155 }
156}
157
158impl SDL_ThreadPriority {
159 pub const LOW: Self = Self((0 as ::core::ffi::c_int));
160 pub const NORMAL: Self = Self((1 as ::core::ffi::c_int));
161 pub const HIGH: Self = Self((2 as ::core::ffi::c_int));
162 pub const TIME_CRITICAL: Self = Self((3 as ::core::ffi::c_int));
163}
164
165pub const SDL_THREAD_PRIORITY_LOW: SDL_ThreadPriority = SDL_ThreadPriority::LOW;
166pub const SDL_THREAD_PRIORITY_NORMAL: SDL_ThreadPriority = SDL_ThreadPriority::NORMAL;
167pub const SDL_THREAD_PRIORITY_HIGH: SDL_ThreadPriority = SDL_ThreadPriority::HIGH;
168pub const SDL_THREAD_PRIORITY_TIME_CRITICAL: SDL_ThreadPriority = SDL_ThreadPriority::TIME_CRITICAL;
169
170#[cfg(feature = "metadata")]
171impl sdl3_sys::metadata::GroupMetadata for SDL_ThreadPriority {
172 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
173 &crate::metadata::thread::METADATA_SDL_ThreadPriority;
174}
175
176/// The SDL thread state.
177///
178/// The current state of a thread can be checked by calling [`SDL_GetThreadState`].
179///
180/// ## Availability
181/// This enum is available since SDL 3.2.0.
182///
183/// ## See also
184/// - [`SDL_GetThreadState`]
185///
186/// ## Known values (`sdl3-sys`)
187/// | Associated constant | Global constant | Description |
188/// | ------------------- | --------------- | ----------- |
189/// | [`UNKNOWN`](SDL_ThreadState::UNKNOWN) | [`SDL_THREAD_UNKNOWN`] | The thread is not valid |
190/// | [`ALIVE`](SDL_ThreadState::ALIVE) | [`SDL_THREAD_ALIVE`] | The thread is currently running |
191/// | [`DETACHED`](SDL_ThreadState::DETACHED) | [`SDL_THREAD_DETACHED`] | The thread is detached and can't be waited on |
192/// | [`COMPLETE`](SDL_ThreadState::COMPLETE) | [`SDL_THREAD_COMPLETE`] | The thread has finished and should be cleaned up with [`SDL_WaitThread()`] |
193#[repr(transparent)]
194#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
195pub struct SDL_ThreadState(pub ::core::ffi::c_int);
196
197impl ::core::cmp::PartialEq<::core::ffi::c_int> for SDL_ThreadState {
198 #[inline(always)]
199 fn eq(&self, other: &::core::ffi::c_int) -> bool {
200 &self.0 == other
201 }
202}
203
204impl ::core::cmp::PartialEq<SDL_ThreadState> for ::core::ffi::c_int {
205 #[inline(always)]
206 fn eq(&self, other: &SDL_ThreadState) -> bool {
207 self == &other.0
208 }
209}
210
211impl From<SDL_ThreadState> for ::core::ffi::c_int {
212 #[inline(always)]
213 fn from(value: SDL_ThreadState) -> Self {
214 value.0
215 }
216}
217
218#[cfg(feature = "debug-impls")]
219impl ::core::fmt::Debug for SDL_ThreadState {
220 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
221 #[allow(unreachable_patterns)]
222 f.write_str(match *self {
223 Self::UNKNOWN => "SDL_THREAD_UNKNOWN",
224 Self::ALIVE => "SDL_THREAD_ALIVE",
225 Self::DETACHED => "SDL_THREAD_DETACHED",
226 Self::COMPLETE => "SDL_THREAD_COMPLETE",
227
228 _ => return write!(f, "SDL_ThreadState({})", self.0),
229 })
230 }
231}
232
233impl SDL_ThreadState {
234 /// The thread is not valid
235 pub const UNKNOWN: Self = Self((0 as ::core::ffi::c_int));
236 /// The thread is currently running
237 pub const ALIVE: Self = Self((1 as ::core::ffi::c_int));
238 /// The thread is detached and can't be waited on
239 pub const DETACHED: Self = Self((2 as ::core::ffi::c_int));
240 /// The thread has finished and should be cleaned up with [`SDL_WaitThread()`]
241 pub const COMPLETE: Self = Self((3 as ::core::ffi::c_int));
242}
243
244/// The thread is not valid
245pub const SDL_THREAD_UNKNOWN: SDL_ThreadState = SDL_ThreadState::UNKNOWN;
246/// The thread is currently running
247pub const SDL_THREAD_ALIVE: SDL_ThreadState = SDL_ThreadState::ALIVE;
248/// The thread is detached and can't be waited on
249pub const SDL_THREAD_DETACHED: SDL_ThreadState = SDL_ThreadState::DETACHED;
250/// The thread has finished and should be cleaned up with [`SDL_WaitThread()`]
251pub const SDL_THREAD_COMPLETE: SDL_ThreadState = SDL_ThreadState::COMPLETE;
252
253#[cfg(feature = "metadata")]
254impl sdl3_sys::metadata::GroupMetadata for SDL_ThreadState {
255 const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
256 &crate::metadata::thread::METADATA_SDL_ThreadState;
257}
258
259/// The function passed to [`SDL_CreateThread()`] as the new thread's entry point.
260///
261/// ## Parameters
262/// - `data`: what was passed as `data` to [`SDL_CreateThread()`].
263///
264/// ## Return value
265/// Returns a value that can be reported through [`SDL_WaitThread()`].
266///
267/// ## Availability
268/// This datatype is available since SDL 3.2.0.
269pub type SDL_ThreadFunction = ::core::option::Option<
270 unsafe extern "C" fn(data: *mut ::core::ffi::c_void) -> ::core::ffi::c_int,
271>;
272
273apply_cfg!(#[cfg(doc)] => {
274 unsafe extern "C" {
275 /// Create a new thread with a default stack size.
276 ///
277 /// This is a convenience function, equivalent to calling
278 /// [`SDL_CreateThreadWithProperties`] with the following properties set:
279 ///
280 /// - [`SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER`]\: `fn`
281 /// - [`SDL_PROP_THREAD_CREATE_NAME_STRING`]\: `name`
282 /// - [`SDL_PROP_THREAD_CREATE_USERDATA_POINTER`]\: `data`
283 ///
284 /// Note that this "function" is actually a macro that calls an internal
285 /// function with two extra parameters not listed here; they are hidden through
286 /// preprocessor macros and are needed to support various C runtimes at the
287 /// point of the function call. Language bindings that aren't using the C
288 /// headers will need to deal with this.
289 ///
290 /// Usually, apps should just call this function the same way on every platform
291 /// and let the macros hide the details.
292 ///
293 /// ## Parameters
294 /// - `fn`: the [`SDL_ThreadFunction`] function to call in the new thread.
295 /// - `name`: the name of the thread.
296 /// - `data`: a pointer that is passed to `fn`.
297 ///
298 /// ## Return value
299 /// Returns an opaque pointer to the new thread object on success, NULL if the
300 /// new thread could not be created; call [`SDL_GetError()`] for more
301 /// information.
302 ///
303 /// ## Availability
304 /// This function is available since SDL 3.2.0.
305 ///
306 /// ## See also
307 /// - [`SDL_CreateThreadWithProperties`]
308 /// - [`SDL_WaitThread`]
309 pub fn SDL_CreateThread(r#fn: SDL_ThreadFunction, name: *const ::core::ffi::c_char, data: *mut ::core::ffi::c_void) -> *mut SDL_Thread;
310 }
311
312 unsafe extern "C" {
313 /// Create a new thread with with the specified properties.
314 ///
315 /// These are the supported properties:
316 ///
317 /// - [`SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER`]\: an [`SDL_ThreadFunction`]
318 /// value that will be called at the start of the new thread's life.
319 /// Required.
320 /// - [`SDL_PROP_THREAD_CREATE_NAME_STRING`]\: the name of the new thread, which
321 /// might be available to debuggers. Optional, defaults to NULL.
322 /// - [`SDL_PROP_THREAD_CREATE_USERDATA_POINTER`]\: an arbitrary app-defined
323 /// pointer, which is passed to the entry function on the new thread, as its
324 /// only parameter. Optional, defaults to NULL.
325 /// - [`SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER`]\: the size, in bytes, of the new
326 /// thread's stack. Optional, defaults to 0 (system-defined default).
327 ///
328 /// SDL makes an attempt to report [`SDL_PROP_THREAD_CREATE_NAME_STRING`] to the
329 /// system, so that debuggers can display it. Not all platforms support this.
330 ///
331 /// Thread naming is a little complicated: Most systems have very small limits
332 /// for the string length (Haiku has 32 bytes, Linux currently has 16, Visual
333 /// C++ 6.0 has _nine_!), and possibly other arbitrary rules. You'll have to
334 /// see what happens with your system's debugger. The name should be UTF-8 (but
335 /// using the naming limits of C identifiers is a better bet). There are no
336 /// requirements for thread naming conventions, so long as the string is
337 /// null-terminated UTF-8, but these guidelines are helpful in choosing a name:
338 ///
339 /// <https://stackoverflow.com/questions/149932/naming-conventions-for-threads>
340 ///
341 /// If a system imposes requirements, SDL will try to munge the string for it
342 /// (truncate, etc), but the original string contents will be available from
343 /// [`SDL_GetThreadName()`].
344 ///
345 /// The size (in bytes) of the new stack can be specified with
346 /// [`SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER`]. Zero means "use the system
347 /// default" which might be wildly different between platforms. x86 Linux
348 /// generally defaults to eight megabytes, an embedded device might be a few
349 /// kilobytes instead. You generally need to specify a stack that is a multiple
350 /// of the system's page size (in many cases, this is 4 kilobytes, but check
351 /// your system documentation).
352 ///
353 /// Note that this "function" is actually a macro that calls an internal
354 /// function with two extra parameters not listed here; they are hidden through
355 /// preprocessor macros and are needed to support various C runtimes at the
356 /// point of the function call. Language bindings that aren't using the C
357 /// headers will need to deal with this.
358 ///
359 /// The actual symbol in SDL is [`SDL_CreateThreadWithPropertiesRuntime`], so
360 /// there is no symbol clash, but trying to load an SDL shared library and look
361 /// for "SDL_CreateThreadWithProperties" will fail.
362 ///
363 /// Usually, apps should just call this function the same way on every platform
364 /// and let the macros hide the details.
365 ///
366 /// ## Parameters
367 /// - `props`: the properties to use.
368 ///
369 /// ## Return value
370 /// Returns an opaque pointer to the new thread object on success, NULL if the
371 /// new thread could not be created; call [`SDL_GetError()`] for more
372 /// information.
373 ///
374 /// ## Availability
375 /// This function is available since SDL 3.2.0.
376 ///
377 /// ## See also
378 /// - [`SDL_CreateThread`]
379 /// - [`SDL_WaitThread`]
380 pub fn SDL_CreateThreadWithProperties(props: SDL_PropertiesID) -> *mut SDL_Thread;
381 }
382
383 pub const SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER: *const ::core::ffi::c_char = c"SDL.thread.create.entry_function".as_ptr();
384
385 pub const SDL_PROP_THREAD_CREATE_NAME_STRING: *const ::core::ffi::c_char = c"SDL.thread.create.name".as_ptr();
386
387 pub const SDL_PROP_THREAD_CREATE_USERDATA_POINTER: *const ::core::ffi::c_char = c"SDL.thread.create.userdata".as_ptr();
388
389 pub const SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER: *const ::core::ffi::c_char = c"SDL.thread.create.stacksize".as_ptr();
390
391});
392
393apply_cfg!(#[cfg(not(doc))] => {
394 apply_cfg!(#[cfg(any(doc, windows))] => {
395 });
396
397});
398
399apply_cfg!(#[cfg(not(doc))] => {
400});
401
402apply_cfg!(#[cfg(not(doc))] => {
403});
404
405apply_cfg!(#[cfg(not(doc))] => {
406 unsafe extern "C" {
407 /// The actual entry point for [`SDL_CreateThread`].
408 ///
409 /// ## Parameters
410 /// - `fn`: the [`SDL_ThreadFunction`] function to call in the new thread
411 /// - `name`: the name of the thread
412 /// - `data`: a pointer that is passed to `fn`
413 /// - `pfnBeginThread`: the C runtime's _beginthreadex (or whatnot). Can be NULL.
414 /// - `pfnEndThread`: the C runtime's _endthreadex (or whatnot). Can be NULL.
415 ///
416 /// ## Return value
417 /// Returns an opaque pointer to the new thread object on success, NULL if the
418 /// new thread could not be created; call [`SDL_GetError()`] for more
419 /// information.
420 ///
421 /// ## Availability
422 /// This function is available since SDL 3.2.0.
423 pub fn SDL_CreateThreadRuntime(r#fn: SDL_ThreadFunction, name: *const ::core::ffi::c_char, data: *mut ::core::ffi::c_void, pfnBeginThread: SDL_FunctionPointer, pfnEndThread: SDL_FunctionPointer) -> *mut SDL_Thread;
424 }
425
426 unsafe extern "C" {
427 /// The actual entry point for [`SDL_CreateThreadWithProperties`].
428 ///
429 /// ## Parameters
430 /// - `props`: the properties to use
431 /// - `pfnBeginThread`: the C runtime's _beginthreadex (or whatnot). Can be NULL.
432 /// - `pfnEndThread`: the C runtime's _endthreadex (or whatnot). Can be NULL.
433 ///
434 /// ## Return value
435 /// Returns an opaque pointer to the new thread object on success, NULL if the
436 /// new thread could not be created; call [`SDL_GetError()`] for more
437 /// information.
438 ///
439 /// ## Availability
440 /// This function is available since SDL 3.2.0.
441 pub fn SDL_CreateThreadWithPropertiesRuntime(props: SDL_PropertiesID, pfnBeginThread: SDL_FunctionPointer, pfnEndThread: SDL_FunctionPointer) -> *mut SDL_Thread;
442 }
443
444 #[cfg(not(windows))]
445 pub const SDL_BeginThreadFunction: SDL_FunctionPointer = unsafe { ::core::mem::transmute::<*const ::core::ffi::c_void, SDL_FunctionPointer>(core::ptr::null()) };
446 #[cfg(not(windows))]
447 pub const SDL_EndThreadFunction: SDL_FunctionPointer = unsafe { ::core::mem::transmute::<*const ::core::ffi::c_void, SDL_FunctionPointer>(core::ptr::null()) };
448 #[cfg(windows)]
449 unsafe extern "cdecl" {
450 fn _beginthreadex(security: *mut ::core::ffi::c_void, stack_size: ::core::ffi::c_uint, start_address: Option<unsafe extern "stdcall" fn(*const ::core::ffi::c_void) -> ::core::ffi::c_uint>, arglist: *mut ::core::ffi::c_void, initflag: ::core::ffi::c_uint, thrdaddr: ::core::ffi::c_uint) -> ::core::primitive::usize;
451 fn _endthreadex(retval: ::core::ffi::c_uint);
452 }
453 #[cfg(windows)]
454 pub const SDL_BeginThreadFunction: SDL_FunctionPointer = unsafe { ::core::mem::transmute::<unsafe extern "cdecl" fn(*mut ::core::ffi::c_void, ::core::ffi::c_uint, Option<unsafe extern "stdcall" fn(*const ::core::ffi::c_void) -> ::core::ffi::c_uint>, *mut ::core::ffi::c_void, ::core::ffi::c_uint, ::core::ffi::c_uint) -> ::core::primitive::usize, SDL_FunctionPointer>(_beginthreadex) };
455 #[cfg(windows)]
456 pub const SDL_EndThreadFunction: SDL_FunctionPointer = unsafe { ::core::mem::transmute::<unsafe extern "cdecl" fn (::core::ffi::c_uint), SDL_FunctionPointer>(_endthreadex) };
457
458 #[inline(always)]
459 pub unsafe fn SDL_CreateThread(r#fn: SDL_ThreadFunction, name: *const ::core::ffi::c_char, data: *mut ::core::ffi::c_void, ) -> *mut SDL_Thread {
460 unsafe { SDL_CreateThreadRuntime((r#fn), (name), (data), SDL_BeginThreadFunction, SDL_EndThreadFunction) }
461 }
462
463
464 #[inline(always)]
465 pub unsafe fn SDL_CreateThreadWithProperties(props: SDL_PropertiesID, ) -> *mut SDL_Thread {
466 unsafe { SDL_CreateThreadWithPropertiesRuntime(props, SDL_BeginThreadFunction, SDL_EndThreadFunction) }
467 }
468
469
470 pub const SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER: *const ::core::ffi::c_char = c"SDL.thread.create.entry_function".as_ptr();
471
472 pub const SDL_PROP_THREAD_CREATE_NAME_STRING: *const ::core::ffi::c_char = c"SDL.thread.create.name".as_ptr();
473
474 pub const SDL_PROP_THREAD_CREATE_USERDATA_POINTER: *const ::core::ffi::c_char = c"SDL.thread.create.userdata".as_ptr();
475
476 pub const SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER: *const ::core::ffi::c_char = c"SDL.thread.create.stacksize".as_ptr();
477
478});
479
480unsafe extern "C" {
481 /// Get the thread name as it was specified in [`SDL_CreateThread()`].
482 ///
483 /// ## Parameters
484 /// - `thread`: the thread to query.
485 ///
486 /// ## Return value
487 /// Returns a pointer to a UTF-8 string that names the specified thread, or
488 /// NULL if it doesn't have a name.
489 ///
490 /// ## Availability
491 /// This function is available since SDL 3.2.0.
492 pub fn SDL_GetThreadName(thread: *mut SDL_Thread) -> *const ::core::ffi::c_char;
493}
494
495unsafe extern "C" {
496 /// Get the thread identifier for the current thread.
497 ///
498 /// This thread identifier is as reported by the underlying operating system.
499 /// If SDL is running on a platform that does not support threads the return
500 /// value will always be zero.
501 ///
502 /// This function also returns a valid thread ID when called from the main
503 /// thread.
504 ///
505 /// ## Return value
506 /// Returns the ID of the current thread.
507 ///
508 /// ## Availability
509 /// This function is available since SDL 3.2.0.
510 ///
511 /// ## See also
512 /// - [`SDL_GetThreadID`]
513 pub safe fn SDL_GetCurrentThreadID() -> SDL_ThreadID;
514}
515
516unsafe extern "C" {
517 /// Get the thread identifier for the specified thread.
518 ///
519 /// This thread identifier is as reported by the underlying operating system.
520 /// If SDL is running on a platform that does not support threads the return
521 /// value will always be zero.
522 ///
523 /// ## Parameters
524 /// - `thread`: the thread to query.
525 ///
526 /// ## Return value
527 /// Returns the ID of the specified thread, or the ID of the current thread if
528 /// `thread` is NULL.
529 ///
530 /// ## Availability
531 /// This function is available since SDL 3.2.0.
532 ///
533 /// ## See also
534 /// - [`SDL_GetCurrentThreadID`]
535 pub fn SDL_GetThreadID(thread: *mut SDL_Thread) -> SDL_ThreadID;
536}
537
538unsafe extern "C" {
539 /// Set the priority for the current thread.
540 ///
541 /// Note that some platforms will not let you alter the priority (or at least,
542 /// promote the thread to a higher priority) at all, and some require you to be
543 /// an administrator account. Be prepared for this to fail.
544 ///
545 /// ## Parameters
546 /// - `priority`: the [`SDL_ThreadPriority`] to set.
547 ///
548 /// ## Return value
549 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
550 /// information.
551 ///
552 /// ## Availability
553 /// This function is available since SDL 3.2.0.
554 pub fn SDL_SetCurrentThreadPriority(priority: SDL_ThreadPriority) -> ::core::primitive::bool;
555}
556
557unsafe extern "C" {
558 /// Wait for a thread to finish.
559 ///
560 /// Threads that haven't been detached will remain until this function cleans
561 /// them up. Not doing so is a resource leak.
562 ///
563 /// Once a thread has been cleaned up through this function, the [`SDL_Thread`]
564 /// that references it becomes invalid and should not be referenced again. As
565 /// such, only one thread may call [`SDL_WaitThread()`] on another.
566 ///
567 /// The return code from the thread function is placed in the area pointed to
568 /// by `status`, if `status` is not NULL.
569 ///
570 /// You may not wait on a thread that has been used in a call to
571 /// [`SDL_DetachThread()`]. Use either that function or this one, but not both, or
572 /// behavior is undefined.
573 ///
574 /// It is safe to pass a NULL thread to this function; it is a no-op.
575 ///
576 /// Note that the thread pointer is freed by this function and is not valid
577 /// afterward.
578 ///
579 /// ## Parameters
580 /// - `thread`: the [`SDL_Thread`] pointer that was returned from the
581 /// [`SDL_CreateThread()`] call that started this thread.
582 /// - `status`: a pointer filled in with the value returned from the thread
583 /// function by its 'return', or -1 if the thread has been
584 /// detached or isn't valid, may be NULL.
585 ///
586 /// ## Availability
587 /// This function is available since SDL 3.2.0.
588 ///
589 /// ## See also
590 /// - [`SDL_CreateThread`]
591 /// - [`SDL_DetachThread`]
592 pub fn SDL_WaitThread(thread: *mut SDL_Thread, status: *mut ::core::ffi::c_int);
593}
594
595unsafe extern "C" {
596 /// Get the current state of a thread.
597 ///
598 /// ## Parameters
599 /// - `thread`: the thread to query.
600 ///
601 /// ## Return value
602 /// Returns the current state of a thread, or [`SDL_THREAD_UNKNOWN`] if the thread
603 /// isn't valid.
604 ///
605 /// ## Availability
606 /// This function is available since SDL 3.2.0.
607 ///
608 /// ## See also
609 /// - [`SDL_ThreadState`]
610 pub fn SDL_GetThreadState(thread: *mut SDL_Thread) -> SDL_ThreadState;
611}
612
613unsafe extern "C" {
614 /// Let a thread clean up on exit without intervention.
615 ///
616 /// A thread may be "detached" to signify that it should not remain until
617 /// another thread has called [`SDL_WaitThread()`] on it. Detaching a thread is
618 /// useful for long-running threads that nothing needs to synchronize with or
619 /// further manage. When a detached thread is done, it simply goes away.
620 ///
621 /// There is no way to recover the return code of a detached thread. If you
622 /// need this, don't detach the thread and instead use [`SDL_WaitThread()`].
623 ///
624 /// Once a thread is detached, you should usually assume the [`SDL_Thread`] isn't
625 /// safe to reference again, as it will become invalid immediately upon the
626 /// detached thread's exit, instead of remaining until someone has called
627 /// [`SDL_WaitThread()`] to finally clean it up. As such, don't detach the same
628 /// thread more than once.
629 ///
630 /// If a thread has already exited when passed to [`SDL_DetachThread()`], it will
631 /// stop waiting for a call to [`SDL_WaitThread()`] and clean up immediately. It is
632 /// not safe to detach a thread that might be used with [`SDL_WaitThread()`].
633 ///
634 /// You may not call [`SDL_WaitThread()`] on a thread that has been detached. Use
635 /// either that function or this one, but not both, or behavior is undefined.
636 ///
637 /// It is safe to pass NULL to this function; it is a no-op.
638 ///
639 /// ## Parameters
640 /// - `thread`: the [`SDL_Thread`] pointer that was returned from the
641 /// [`SDL_CreateThread()`] call that started this thread.
642 ///
643 /// ## Availability
644 /// This function is available since SDL 3.2.0.
645 ///
646 /// ## See also
647 /// - [`SDL_CreateThread`]
648 /// - [`SDL_WaitThread`]
649 pub fn SDL_DetachThread(thread: *mut SDL_Thread);
650}
651
652unsafe extern "C" {
653 /// Get the current thread's value associated with a thread local storage ID.
654 ///
655 /// ## Parameters
656 /// - `id`: a pointer to the thread local storage ID, may not be NULL.
657 ///
658 /// ## Return value
659 /// Returns the value associated with the ID for the current thread or NULL if
660 /// no value has been set; call [`SDL_GetError()`] for more information.
661 ///
662 /// ## Thread safety
663 /// It is safe to call this function from any thread.
664 ///
665 /// ## Availability
666 /// This function is available since SDL 3.2.0.
667 ///
668 /// ## See also
669 /// - [`SDL_SetTLS`]
670 pub fn SDL_GetTLS(id: *mut SDL_TLSID) -> *mut ::core::ffi::c_void;
671}
672
673/// The callback used to cleanup data passed to [`SDL_SetTLS`].
674///
675/// This is called when a thread exits, to allow an app to free any resources.
676///
677/// ## Parameters
678/// - `value`: a pointer previously handed to [`SDL_SetTLS`].
679///
680/// ## Availability
681/// This datatype is available since SDL 3.2.0.
682///
683/// ## See also
684/// - [`SDL_SetTLS`]
685pub type SDL_TLSDestructorCallback =
686 ::core::option::Option<unsafe extern "C" fn(value: *mut ::core::ffi::c_void)>;
687
688unsafe extern "C" {
689 /// Set the current thread's value associated with a thread local storage ID.
690 ///
691 /// If the thread local storage ID is not initialized (the value is 0), a new
692 /// ID will be created in a thread-safe way, so all calls using a pointer to
693 /// the same ID will refer to the same local storage.
694 ///
695 /// Note that replacing a value from a previous call to this function on the
696 /// same thread does _not_ call the previous value's destructor!
697 ///
698 /// `destructor` can be NULL; it is assumed that `value` does not need to be
699 /// cleaned up if so.
700 ///
701 /// ## Parameters
702 /// - `id`: a pointer to the thread local storage ID, may not be NULL.
703 /// - `value`: the value to associate with the ID for the current thread.
704 /// - `destructor`: a function called when the thread exits, to free the
705 /// value, may be NULL.
706 ///
707 /// ## Return value
708 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
709 /// information.
710 ///
711 /// ## Thread safety
712 /// It is safe to call this function from any thread.
713 ///
714 /// ## Availability
715 /// This function is available since SDL 3.2.0.
716 ///
717 /// ## See also
718 /// - [`SDL_GetTLS`]
719 pub fn SDL_SetTLS(
720 id: *mut SDL_TLSID,
721 value: *const ::core::ffi::c_void,
722 destructor: SDL_TLSDestructorCallback,
723 ) -> ::core::primitive::bool;
724}
725
726unsafe extern "C" {
727 /// Cleanup all TLS data for this thread.
728 ///
729 /// If you are creating your threads outside of SDL and then calling SDL
730 /// functions, you should call this function before your thread exits, to
731 /// properly clean up SDL memory.
732 ///
733 /// ## Thread safety
734 /// It is safe to call this function from any thread.
735 ///
736 /// ## Availability
737 /// This function is available since SDL 3.2.0.
738 pub fn SDL_CleanupTLS();
739}
740
741/// The SDL thread object.
742///
743/// These are opaque data.
744///
745/// ## Availability
746/// This datatype is available since SDL 3.2.0.
747///
748/// ## See also
749/// - [`SDL_CreateThread`]
750/// - [`SDL_WaitThread`]
751#[repr(C)]
752pub struct SDL_Thread {
753 _opaque: [::core::primitive::u8; 0],
754}
755
756#[cfg(doc)]
757use crate::everything::*;