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::*;