include/SDL_thread.h
author Sam Lantinga <slouken@libsdl.org>
Sat, 27 Jul 2013 03:44:03 -0700
changeset 7528 1890a896802f
parent 7482 249d8ecbbb7d
child 7653 9a0e274b8aa7
permissions -rw-r--r--
Fixed bug 1983 - SDL_thread.h broken under MinGW crosscompiling environment

q66

after updating SDL2 to the latest RC I'm unable to build my game engine under mingw crosscompiling environment for Windows (32bit, hosted on freebsd 64bit).

The error is in SDL_thread.h with messages like this: http://codepad.org/jEQXd3Yq

The problem is, while _beginthreadex return type is correctly mapped to uintptr_t (as specified by Microsoft), the return type under mingw is unsigned long int (same size, different signature), resulting in the error above.

The reason it didn't error before is this: http://codepad.org/8FAbKAxz

You can see the _beginthreadex case is only used without HAVE_LIBC defined; at one point though, SDL_config_windows.h was changed like this:

-/* Enabled for SDL 1.2 (binary compatibility) */
-#define HAVE_LIBC 1
+/* This is disabled by default to avoid C runtime dependencies and manifest requirements */

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