]>
Commit | Line | Data |
---|---|---|
7407ac7f BB |
1 | /* |
2 | Simple DirectMedia Layer | |
3 | Copyright (C) 1997-2013 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 | #ifndef _SDL_thread_h | |
23 | #define _SDL_thread_h | |
24 | ||
25 | /** | |
26 | * \file SDL_thread.h | |
27 | * | |
28 | * Header for the SDL thread management routines. | |
29 | */ | |
30 | ||
31 | #include "SDL_stdinc.h" | |
32 | #include "SDL_error.h" | |
33 | ||
34 | /* Thread synchronization primitives */ | |
35 | #include "SDL_atomic.h" | |
36 | #include "SDL_mutex.h" | |
37 | ||
38 | #include "begin_code.h" | |
39 | /* Set up for C function definitions, even when using C++ */ | |
40 | #ifdef __cplusplus | |
41 | extern "C" { | |
42 | #endif | |
43 | ||
44 | /* The SDL thread structure, defined in SDL_thread.c */ | |
45 | struct SDL_Thread; | |
46 | typedef struct SDL_Thread SDL_Thread; | |
47 | ||
48 | /* The SDL thread ID */ | |
49 | typedef unsigned long SDL_threadID; | |
50 | ||
51 | /* Thread local storage ID, 0 is the invalid ID */ | |
52 | typedef unsigned int SDL_TLSID; | |
53 | ||
54 | /* The SDL thread priority | |
55 | * | |
56 | * Note: On many systems you require special privileges to set high priority. | |
57 | */ | |
58 | typedef enum { | |
59 | SDL_THREAD_PRIORITY_LOW, | |
60 | SDL_THREAD_PRIORITY_NORMAL, | |
61 | SDL_THREAD_PRIORITY_HIGH | |
62 | } SDL_ThreadPriority; | |
63 | ||
64 | /* The function passed to SDL_CreateThread() | |
65 | It is passed a void* user context parameter and returns an int. | |
66 | */ | |
67 | typedef int (SDLCALL * SDL_ThreadFunction) (void *data); | |
68 | ||
69 | #if defined(__WIN32__) && !defined(HAVE_LIBC) | |
70 | /** | |
71 | * \file SDL_thread.h | |
72 | * | |
73 | * We compile SDL into a DLL. This means, that it's the DLL which | |
74 | * creates a new thread for the calling process with the SDL_CreateThread() | |
75 | * API. There is a problem with this, that only the RTL of the SDL.DLL will | |
76 | * be initialized for those threads, and not the RTL of the calling | |
77 | * application! | |
78 | * | |
79 | * To solve this, we make a little hack here. | |
80 | * | |
81 | * We'll always use the caller's _beginthread() and _endthread() APIs to | |
82 | * start a new thread. This way, if it's the SDL.DLL which uses this API, | |
83 | * then the RTL of SDL.DLL will be used to create the new thread, and if it's | |
84 | * the application, then the RTL of the application will be used. | |
85 | * | |
86 | * So, in short: | |
87 | * Always use the _beginthread() and _endthread() of the calling runtime | |
88 | * library! | |
89 | */ | |
90 | #define SDL_PASSED_BEGINTHREAD_ENDTHREAD | |
91 | #include <process.h> /* This has _beginthread() and _endthread() defined! */ | |
92 | ||
93 | typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned, | |
94 | unsigned (__stdcall * | |
95 | func) (void | |
96 | *), | |
97 | void *arg, unsigned, | |
98 | unsigned *threadID); | |
99 | typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code); | |
100 | ||
101 | /** | |
102 | * Create a thread. | |
103 | */ | |
104 | extern DECLSPEC SDL_Thread *SDLCALL | |
105 | SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data, | |
106 | pfnSDL_CurrentBeginThread pfnBeginThread, | |
107 | pfnSDL_CurrentEndThread pfnEndThread); | |
108 | ||
109 | /** | |
110 | * Create a thread. | |
111 | */ | |
112 | #define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex) | |
113 | ||
114 | #else | |
115 | ||
116 | /** | |
117 | * Create a thread. | |
118 | * | |
119 | * Thread naming is a little complicated: Most systems have very small | |
120 | * limits for the string length (BeOS has 32 bytes, Linux currently has 16, | |
121 | * Visual C++ 6.0 has nine!), and possibly other arbitrary rules. You'll | |
122 | * have to see what happens with your system's debugger. The name should be | |
123 | * UTF-8 (but using the naming limits of C identifiers is a better bet). | |
124 | * There are no requirements for thread naming conventions, so long as the | |
125 | * string is null-terminated UTF-8, but these guidelines are helpful in | |
126 | * choosing a name: | |
127 | * | |
128 | * http://stackoverflow.com/questions/149932/naming-conventions-for-threads | |
129 | * | |
130 | * If a system imposes requirements, SDL will try to munge the string for | |
131 | * it (truncate, etc), but the original string contents will be available | |
132 | * from SDL_GetThreadName(). | |
133 | */ | |
134 | extern DECLSPEC SDL_Thread *SDLCALL | |
135 | SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); | |
136 | ||
137 | #endif | |
138 | ||
139 | /** | |
140 | * Get the thread name, as it was specified in SDL_CreateThread(). | |
141 | * This function returns a pointer to a UTF-8 string that names the | |
142 | * specified thread, or NULL if it doesn't have a name. This is internal | |
143 | * memory, not to be free()'d by the caller, and remains valid until the | |
144 | * specified thread is cleaned up by SDL_WaitThread(). | |
145 | */ | |
146 | extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread); | |
147 | ||
148 | /** | |
149 | * Get the thread identifier for the current thread. | |
150 | */ | |
151 | extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void); | |
152 | ||
153 | /** | |
154 | * Get the thread identifier for the specified thread. | |
155 | * | |
156 | * Equivalent to SDL_ThreadID() if the specified thread is NULL. | |
157 | */ | |
158 | extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); | |
159 | ||
160 | /** | |
161 | * Set the priority for the current thread | |
162 | */ | |
163 | extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority); | |
164 | ||
165 | /** | |
166 | * Wait for a thread to finish. | |
167 | * | |
168 | * The return code for the thread function is placed in the area | |
169 | * pointed to by \c status, if \c status is not NULL. | |
170 | */ | |
171 | extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status); | |
172 | ||
173 | /** | |
174 | * \brief Create an identifier that is globally visible to all threads but refers to data that is thread-specific. | |
175 | * | |
176 | * \return The newly created thread local storage identifier, or 0 on error | |
177 | * | |
178 | * \code | |
179 | * static SDL_SpinLock tls_lock; | |
180 | * static SDL_TLSID thread_local_storage; | |
181 | * | |
182 | * void SetMyThreadData(void *value) | |
183 | * { | |
184 | * if (!thread_local_storage) { | |
185 | * SDL_AtomicLock(&tls_lock); | |
186 | * if (!thread_local_storage) { | |
187 | * thread_local_storage = SDL_TLSCreate(); | |
188 | * } | |
189 | * SDL_AtomicUnLock(&tls_lock); | |
190 | * } | |
191 | * SDL_TLSSet(thread_local_storage, value); | |
192 | * } | |
193 | * | |
194 | * void *GetMyThreadData(void) | |
195 | * { | |
196 | * return SDL_TLSGet(thread_local_storage); | |
197 | * } | |
198 | * \endcode | |
199 | * | |
200 | * \sa SDL_TLSGet() | |
201 | * \sa SDL_TLSSet() | |
202 | */ | |
203 | extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate(void); | |
204 | ||
205 | /** | |
206 | * \brief Get the value associated with a thread local storage ID for the current thread. | |
207 | * | |
208 | * \param id The thread local storage ID | |
209 | * | |
210 | * \return The value associated with the ID for the current thread, or NULL if no value has been set. | |
211 | * | |
212 | * \sa SDL_TLSCreate() | |
213 | * \sa SDL_TLSSet() | |
214 | */ | |
215 | extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id); | |
216 | ||
217 | /** | |
218 | * \brief Set the value associated with a thread local storage ID for the current thread. | |
219 | * | |
220 | * \param id The thread local storage ID | |
221 | * \param value The value to associate with the ID for the current thread | |
222 | * \param destructor A function called when the thread exits, to free the value. | |
223 | * | |
224 | * \return 0 on success, -1 on error | |
225 | * | |
226 | * \sa SDL_TLSCreate() | |
227 | * \sa SDL_TLSGet() | |
228 | */ | |
229 | extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value, void (*destructor)(void*)); | |
230 | ||
231 | ||
232 | /* Ends C function definitions when using C++ */ | |
233 | #ifdef __cplusplus | |
234 | } | |
235 | #endif | |
236 | #include "close_code.h" | |
237 | ||
238 | #endif /* _SDL_thread_h */ | |
239 | ||
240 | /* vi: set ts=4 sw=4 expandtab: */ |