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 }