1 
2 //          Copyright 2018 - 2021 Michael D. Parker
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 module bindbc.sdl.bind.sdlthread;
8 
9 import core.stdc.config : c_ulong;
10 import bindbc.sdl.config;
11 
12 struct SDL_Thread;
13 alias SDL_threadID = c_ulong;
14 alias SDL_TLSID = uint;
15 
16 static if(sdlSupport >= SDLSupport.sdl209) {
17     enum SDL_ThreadPriority {
18         SDL_THREAD_PRIORITY_LOW,
19         SDL_THREAD_PRIORITY_NORMAL,
20         SDL_THREAD_PRIORITY_HIGH,
21         SDL_THREAD_PRIORITY_TIME_CRITICAL,
22     }
23 }
24 else {
25     enum SDL_ThreadPriority {
26         SDL_THREAD_PRIORITY_LOW,
27         SDL_THREAD_PRIORITY_NORMAL,
28         SDL_THREAD_PRIORITY_HIGH,
29     }
30 }
31 mixin(expandEnum!SDL_ThreadPriority);
32 
33 extern(C) nothrow {
34     alias SDL_ThreadFunction = int function(void*);
35     alias TLSDestructor = void function(void*);
36 }
37 
38 version(Windows) {
39     /*
40     On Windows, SDL_CreateThread/WithStackSize require the _beginthreadex/_endthreadex of
41     the caller's process when using the DLL. As best as I can tell, this will be okay even
42     when statically linking. If it does break, I'll need to add a new version identifier
43     when BindBC_Static is specified in order to distingiuish between linking with the
44     DLL's import library and statically linking with SDL.
45     */
46     private {
47         import core.stdc.stdint : uintptr_t;
48 
49         extern(Windows) alias btex_fptr = uint function(void*);
50         extern(C) @nogc nothrow {
51             uintptr_t _beginthreadex(void*,uint,btex_fptr,void*,uint,uint*);
52             void _endthreadex(uint);
53 
54             alias pfnSDL_CurrentBeginThread = uintptr_t function(void*,uint,btex_fptr,void*,uint,uint*);
55             alias pfnSDL_CurrentEndThread = void function(uint);
56         }
57     }
58 
59     SDL_Thread* SDL_CreateThreadImpl(SDL_ThreadFunction fn, const(char)* name, void* data) {
60         return SDL_CreateThread(fn, name, data, &_beginthreadex, &_endthreadex);
61     }
62 
63     static if(sdlSupport >= SDLSupport.sdl209) {
64         SDL_Thread* SDL_CreateThreadWithStackSizeImpl(SDL_ThreadFunction fn, const(char)* name, const(size_t) stackSize, void* data) {
65             return SDL_CreateThreadWithStackSize(fn, name, stackSize, data, &_beginthreadex, &_endthreadex);
66         }
67     }
68 }
69 
70 
71 static if(staticBinding) {
72     extern(C) @nogc nothrow {
73         version(Windows) SDL_Thread* SDL_CreateThread(SDL_ThreadFunction fn, const(char)* name, void* data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
74         else SDL_Thread* SDL_CreateThread(SDL_ThreadFunction,const(char)*,void*);
75 
76         const(char)* SDL_GetThreadName(SDL_Thread* thread);
77         SDL_threadID SDL_ThreadID();
78         SDL_threadID SDL_GetThreadID(SDL_Thread* thread);
79         int SDL_SetThreadPriority(SDL_ThreadPriority priority);
80         void SDL_WaitThread(SDL_Thread* thread, int* status);
81         SDL_TLSID SDL_TLSCreate();
82         void* SDL_TLSGet(SDL_TLSID id);
83         int SDL_TLSSet(SDL_TLSID id,const(void)* value, TLSDestructor destructor);
84 
85         static if(sdlSupport >= SDLSupport.sdl202) {
86             void SDL_DetachThread(SDL_Thread* thread);
87         }
88         static if(sdlSupport >= SDLSupport.sdl209) {
89             version(Windows) SDL_Thread* SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const(char)* name, const(size_t) stacksize, void* data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
90             else SDL_Thread* SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const(char)* name, const(size_t) stacksize, void* data);
91         }
92     }
93 }
94 else {
95     extern(C) @nogc nothrow {
96         version(Windows)alias pSDL_CreateThread = SDL_Thread* function(SDL_ThreadFunction fn, const(char)* name, void* data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
97         else alias pSDL_CreateThread = SDL_Thread* function(SDL_ThreadFunction fn, const(char)*  name, void* data);
98 
99         alias pSDL_GetThreadName = const(char)* function(SDL_Thread* thread);
100         alias pSDL_ThreadID = SDL_threadID function();
101         alias pSDL_GetThreadID = SDL_threadID function(SDL_Thread* thread);
102         alias pSDL_SetThreadPriority = int function(SDL_ThreadPriority priority);
103         alias pSDL_WaitThread = void function(SDL_Thread* thread, int* status);
104         alias pSDL_TLSCreate = SDL_TLSID function();
105         alias pSDL_TLSGet = void* function(SDL_TLSID id);
106         alias pSDL_TLSSet = int function(SDL_TLSID id,const(void)* value, TLSDestructor destructor);
107     }
108 
109     __gshared {
110         pSDL_CreateThread SDL_CreateThread;
111         pSDL_GetThreadName SDL_GetThreadName;
112         pSDL_ThreadID SDL_ThreadID;
113         pSDL_GetThreadID SDL_GetThreadID;
114         pSDL_SetThreadPriority SDL_SetThreadPriority;
115         pSDL_WaitThread SDL_WaitThread;
116         pSDL_TLSCreate SDL_TLSCreate;
117         pSDL_TLSGet SDL_TLSGet;
118         pSDL_TLSSet SDL_TLSSet;
119     }
120 
121     static if(sdlSupport >= SDLSupport.sdl202) {
122         extern(C) @nogc nothrow {
123             alias pSDL_DetachThread = void function(SDL_Thread* thread);
124         }
125         __gshared {
126             pSDL_DetachThread SDL_DetachThread;
127         }
128     }
129     static if(sdlSupport >= SDLSupport.sdl209) {
130 
131         extern(C) @nogc nothrow {
132             version(Windows) alias pSDL_CreateThreadWithStackSize = SDL_Thread* function(SDL_ThreadFunction fn, const(char)* name, const(size_t) stacksize, void* data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread);
133             else alias pSDL_CreateThreadWithStackSize = SDL_Thread* function(SDL_ThreadFunction fn, const(char)* name, const(size_t) stacksize, void* data);
134         }
135 
136         __gshared {
137             pSDL_CreateThreadWithStackSize SDL_CreateThreadWithStackSize;
138         }
139     }
140 }