include/SDL_thread.h
author Steven M. Vascellaro <svascellaro@gmail.com>
Mon, 22 Oct 2018 10:55:18 -0400
changeset 12379 5dc13016cf34
parent 12318 69ebb2ebced0
child 12503 806492103856
permissions -rw-r--r--
joystick: Add Linux mappings for "Xbox One Wireless Controller (Model 1708)"

Adds controller bindings to support the "Xbox One Wireless Controller
(Model 1708)" on Linux. The Model 1708 was released in 2016 alongside the
Xbox One S. It is the current model being sold by Microsoft as of writing.
(October 22, 2018)
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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@10638
    22
#ifndef SDL_thread_h_
slouken@10638
    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
philipp@7653
    54
/**
philipp@7653
    55
 *  The SDL thread priority.
slouken@5506
    56
 *
slouken@11952
    57
 *  \note On many systems you require special privileges to set high or time critical priority.
slouken@5506
    58
 */
slouken@5506
    59
typedef enum {
slouken@5506
    60
    SDL_THREAD_PRIORITY_LOW,
slouken@5506
    61
    SDL_THREAD_PRIORITY_NORMAL,
slouken@11952
    62
    SDL_THREAD_PRIORITY_HIGH,
slouken@11952
    63
    SDL_THREAD_PRIORITY_TIME_CRITICAL
slouken@5506
    64
} SDL_ThreadPriority;
slouken@5506
    65
philipp@7653
    66
/**
philipp@7653
    67
 *  The function passed to SDL_CreateThread().
philipp@7653
    68
 *  It is passed a void* user context parameter and returns an int.
slouken@4866
    69
 */
slouken@4866
    70
typedef int (SDLCALL * SDL_ThreadFunction) (void *data);
slouken@4866
    71
slouken@5086
    72
#if defined(__WIN32__) && !defined(HAVE_LIBC)
slouken@3407
    73
/**
slouken@3407
    74
 *  \file SDL_thread.h
slouken@7191
    75
 *
slouken@3407
    76
 *  We compile SDL into a DLL. This means, that it's the DLL which
slouken@3407
    77
 *  creates a new thread for the calling process with the SDL_CreateThread()
philipp@10901
    78
 *  API. There is a problem with this, that only the RTL of the SDL2.DLL will
slouken@7191
    79
 *  be initialized for those threads, and not the RTL of the calling
slouken@3407
    80
 *  application!
slouken@7191
    81
 *
slouken@3407
    82
 *  To solve this, we make a little hack here.
slouken@7191
    83
 *
slouken@3407
    84
 *  We'll always use the caller's _beginthread() and _endthread() APIs to
philipp@10901
    85
 *  start a new thread. This way, if it's the SDL2.DLL which uses this API,
philipp@10901
    86
 *  then the RTL of SDL2.DLL will be used to create the new thread, and if it's
slouken@3407
    87
 *  the application, then the RTL of the application will be used.
slouken@7191
    88
 *
slouken@3407
    89
 *  So, in short:
slouken@7191
    90
 *  Always use the _beginthread() and _endthread() of the calling runtime
slouken@3407
    91
 *  library!
slouken@3407
    92
 */
slouken@1471
    93
#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@11543
    94
#include <process.h> /* _beginthreadex() and _endthreadex() */
icculus@1190
    95
slouken@11543
    96
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread)
slouken@11543
    97
                   (void *, unsigned, unsigned (__stdcall *func)(void *),
slouken@11543
    98
                    void * /*arg*/, unsigned, 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
icculus@12317
   109
extern DECLSPEC SDL_Thread *SDLCALL
icculus@12317
   110
SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
icculus@12317
   111
                 const char *name, const size_t stacksize, void *data,
icculus@12317
   112
                 pfnSDL_CurrentBeginThread pfnBeginThread,
icculus@12317
   113
                 pfnSDL_CurrentEndThread pfnEndThread);
icculus@12317
   114
icculus@12317
   115
slouken@3407
   116
/**
slouken@3407
   117
 *  Create a thread.
slouken@3407
   118
 */
icculus@8094
   119
#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
icculus@8094
   120
#undef SDL_CreateThread
icculus@8094
   121
#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
sezeroz@12318
   122
#undef SDL_CreateThreadWithStackSize
icculus@12317
   123
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
icculus@8094
   124
#else
slouken@7528
   125
#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
icculus@12317
   126
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
icculus@8094
   127
#endif
slouken@3407
   128
slouken@11340
   129
#elif defined(__OS2__)
slouken@11340
   130
/*
slouken@11340
   131
 * just like the windows case above:  We compile SDL2
slouken@11340
   132
 * into a dll with Watcom's runtime statically linked.
slouken@11340
   133
 */
slouken@11340
   134
#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@11543
   135
#ifndef __EMX__
slouken@11340
   136
#include <process.h>
slouken@11543
   137
#else
slouken@11543
   138
#include <stdlib.h>
slouken@11543
   139
#endif
slouken@11356
   140
typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void * /*arg*/);
slouken@11340
   141
typedef void (*pfnSDL_CurrentEndThread)(void);
slouken@11356
   142
extern DECLSPEC SDL_Thread *SDLCALL
slouken@11356
   143
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
slouken@11356
   144
                 pfnSDL_CurrentBeginThread pfnBeginThread,
slouken@11356
   145
                 pfnSDL_CurrentEndThread pfnEndThread);
icculus@12317
   146
extern DECLSPEC SDL_Thread *SDLCALL
icculus@12317
   147
SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data,
icculus@12317
   148
                 pfnSDL_CurrentBeginThread pfnBeginThread,
icculus@12317
   149
                 pfnSDL_CurrentEndThread pfnEndThread);
slouken@11356
   150
#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
slouken@11340
   151
#undef SDL_CreateThread
slouken@11356
   152
#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
sezeroz@12318
   153
#undef SDL_CreateThreadWithStackSize
icculus@12317
   154
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
slouken@11356
   155
#else
slouken@11340
   156
#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
icculus@12317
   157
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
slouken@11356
   158
#endif
slouken@11340
   159
icculus@1190
   160
#else
slouken@3407
   161
slouken@3407
   162
/**
icculus@12317
   163
 *  Create a thread with a default stack size.
icculus@12317
   164
 *
icculus@12317
   165
 *  This is equivalent to calling:
icculus@12317
   166
 *  SDL_CreateThreadWithStackSize(fn, name, 0, data);
icculus@12317
   167
 */
icculus@12317
   168
extern DECLSPEC SDL_Thread *SDLCALL
icculus@12317
   169
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
icculus@12317
   170
icculus@12317
   171
/**
slouken@3407
   172
 *  Create a thread.
icculus@5969
   173
 *
icculus@5969
   174
 *   Thread naming is a little complicated: Most systems have very small
icculus@7981
   175
 *    limits for the string length (Haiku has 32 bytes, Linux currently has 16,
icculus@5969
   176
 *    Visual C++ 6.0 has nine!), and possibly other arbitrary rules. You'll
icculus@5969
   177
 *    have to see what happens with your system's debugger. The name should be
icculus@5969
   178
 *    UTF-8 (but using the naming limits of C identifiers is a better bet).
icculus@5969
   179
 *   There are no requirements for thread naming conventions, so long as the
icculus@5969
   180
 *    string is null-terminated UTF-8, but these guidelines are helpful in
icculus@5969
   181
 *    choosing a name:
icculus@5969
   182
 *
icculus@5969
   183
 *    http://stackoverflow.com/questions/149932/naming-conventions-for-threads
icculus@5969
   184
 *
icculus@5969
   185
 *   If a system imposes requirements, SDL will try to munge the string for
icculus@5969
   186
 *    it (truncate, etc), but the original string contents will be available
icculus@5969
   187
 *    from SDL_GetThreadName().
icculus@12317
   188
 *
icculus@12317
   189
 *   The size (in bytes) of the new stack can be specified. Zero means "use
icculus@12317
   190
 *    the system default" which might be wildly different between platforms
icculus@12317
   191
 *    (x86 Linux generally defaults to eight megabytes, an embedded device
icculus@12317
   192
 *    might be a few kilobytes instead).
icculus@12317
   193
 *
icculus@12317
   194
 *   In SDL 2.1, stacksize will be folded into the original SDL_CreateThread
icculus@12317
   195
 *    function.
slouken@3407
   196
 */
slouken@1895
   197
extern DECLSPEC SDL_Thread *SDLCALL
icculus@12317
   198
SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data);
slouken@3407
   199
icculus@1190
   200
#endif
slouken@0
   201
slouken@3407
   202
/**
icculus@5969
   203
 * Get the thread name, as it was specified in SDL_CreateThread().
icculus@5969
   204
 *  This function returns a pointer to a UTF-8 string that names the
icculus@5969
   205
 *  specified thread, or NULL if it doesn't have a name. This is internal
icculus@5969
   206
 *  memory, not to be free()'d by the caller, and remains valid until the
icculus@5969
   207
 *  specified thread is cleaned up by SDL_WaitThread().
icculus@5969
   208
 */
icculus@5969
   209
extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread);
icculus@5969
   210
icculus@5969
   211
/**
slouken@3578
   212
 *  Get the thread identifier for the current thread.
slouken@3407
   213
 */
slouken@3578
   214
extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void);
slouken@0
   215
slouken@3407
   216
/**
slouken@3578
   217
 *  Get the thread identifier for the specified thread.
slouken@7191
   218
 *
slouken@3407
   219
 *  Equivalent to SDL_ThreadID() if the specified thread is NULL.
slouken@0
   220
 */
slouken@3578
   221
extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread);
slouken@0
   222
slouken@3407
   223
/**
slouken@5509
   224
 *  Set the priority for the current thread
slouken@5506
   225
 */
slouken@5509
   226
extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority);
slouken@5506
   227
slouken@5506
   228
/**
icculus@7978
   229
 *  Wait for a thread to finish. Threads that haven't been detached will
icculus@7978
   230
 *  remain (as a "zombie") until this function cleans them up. Not doing so
icculus@7978
   231
 *  is a resource leak.
icculus@7978
   232
 *
icculus@7978
   233
 *  Once a thread has been cleaned up through this function, the SDL_Thread
icculus@7978
   234
 *  that references it becomes invalid and should not be referenced again.
icculus@7978
   235
 *  As such, only one thread may call SDL_WaitThread() on another.
slouken@7191
   236
 *
slouken@3407
   237
 *  The return code for the thread function is placed in the area
slouken@3407
   238
 *  pointed to by \c status, if \c status is not NULL.
icculus@7978
   239
 *
icculus@7978
   240
 *  You may not wait on a thread that has been used in a call to
icculus@7978
   241
 *  SDL_DetachThread(). Use either that function or this one, but not
icculus@7978
   242
 *  both, or behavior is undefined.
icculus@7978
   243
 *
icculus@7978
   244
 *  It is safe to pass NULL to this function; it is a no-op.
slouken@0
   245
 */
slouken@1895
   246
extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
slouken@0
   247
slouken@7391
   248
/**
icculus@7978
   249
 *  A thread may be "detached" to signify that it should not remain until
icculus@7978
   250
 *  another thread has called SDL_WaitThread() on it. Detaching a thread
icculus@7978
   251
 *  is useful for long-running threads that nothing needs to synchronize
icculus@7978
   252
 *  with or further manage. When a detached thread is done, it simply
icculus@7978
   253
 *  goes away.
icculus@7978
   254
 *
icculus@7978
   255
 *  There is no way to recover the return code of a detached thread. If you
icculus@7978
   256
 *  need this, don't detach the thread and instead use SDL_WaitThread().
icculus@7978
   257
 *
icculus@7978
   258
 *  Once a thread is detached, you should usually assume the SDL_Thread isn't
icculus@7978
   259
 *  safe to reference again, as it will become invalid immediately upon
icculus@7978
   260
 *  the detached thread's exit, instead of remaining until someone has called
icculus@7978
   261
 *  SDL_WaitThread() to finally clean it up. As such, don't detach the same
icculus@7978
   262
 *  thread more than once.
icculus@7978
   263
 *
icculus@7978
   264
 *  If a thread has already exited when passed to SDL_DetachThread(), it will
icculus@7978
   265
 *  stop waiting for a call to SDL_WaitThread() and clean up immediately.
icculus@7978
   266
 *  It is not safe to detach a thread that might be used with SDL_WaitThread().
icculus@7978
   267
 *
icculus@7978
   268
 *  You may not call SDL_WaitThread() on a thread that has been detached.
icculus@7978
   269
 *  Use either that function or this one, but not both, or behavior is
icculus@7978
   270
 *  undefined.
icculus@7978
   271
 *
icculus@7978
   272
 *  It is safe to pass NULL to this function; it is a no-op.
icculus@7978
   273
 */
icculus@7978
   274
extern DECLSPEC void SDLCALL SDL_DetachThread(SDL_Thread * thread);
icculus@7978
   275
icculus@7978
   276
/**
slouken@7391
   277
 *  \brief Create an identifier that is globally visible to all threads but refers to data that is thread-specific.
slouken@7391
   278
 *
slouken@7391
   279
 *  \return The newly created thread local storage identifier, or 0 on error
slouken@7391
   280
 *
slouken@7391
   281
 *  \code
slouken@7391
   282
 *  static SDL_SpinLock tls_lock;
slouken@7391
   283
 *  static SDL_TLSID thread_local_storage;
slouken@7391
   284
 * 
slouken@7391
   285
 *  void SetMyThreadData(void *value)
slouken@7391
   286
 *  {
slouken@7391
   287
 *      if (!thread_local_storage) {
slouken@7391
   288
 *          SDL_AtomicLock(&tls_lock);
slouken@7391
   289
 *          if (!thread_local_storage) {
slouken@7391
   290
 *              thread_local_storage = SDL_TLSCreate();
slouken@7391
   291
 *          }
philipp@9125
   292
 *          SDL_AtomicUnlock(&tls_lock);
slouken@7391
   293
 *      }
philipp@9125
   294
 *      SDL_TLSSet(thread_local_storage, value, 0);
slouken@7391
   295
 *  }
slouken@7391
   296
 *  
slouken@7391
   297
 *  void *GetMyThreadData(void)
slouken@7391
   298
 *  {
slouken@7391
   299
 *      return SDL_TLSGet(thread_local_storage);
slouken@7391
   300
 *  }
slouken@7391
   301
 *  \endcode
slouken@7391
   302
 *
slouken@7391
   303
 *  \sa SDL_TLSGet()
slouken@7391
   304
 *  \sa SDL_TLSSet()
slouken@7391
   305
 */
dimitris@7418
   306
extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate(void);
slouken@7391
   307
slouken@7391
   308
/**
slouken@7391
   309
 *  \brief Get the value associated with a thread local storage ID for the current thread.
slouken@7391
   310
 *
slouken@7391
   311
 *  \param id The thread local storage ID
slouken@7391
   312
 *
slouken@7391
   313
 *  \return The value associated with the ID for the current thread, or NULL if no value has been set.
slouken@7391
   314
 *
slouken@7391
   315
 *  \sa SDL_TLSCreate()
slouken@7391
   316
 *  \sa SDL_TLSSet()
slouken@7391
   317
 */
slouken@7391
   318
extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id);
slouken@7391
   319
slouken@7391
   320
/**
slouken@7391
   321
 *  \brief Set the value associated with a thread local storage ID for the current thread.
slouken@7391
   322
 *
slouken@7391
   323
 *  \param id The thread local storage ID
slouken@7391
   324
 *  \param value The value to associate with the ID for the current thread
slouken@7393
   325
 *  \param destructor A function called when the thread exits, to free the value.
slouken@7391
   326
 *
slouken@7391
   327
 *  \return 0 on success, -1 on error
slouken@7391
   328
 *
slouken@7391
   329
 *  \sa SDL_TLSCreate()
slouken@7391
   330
 *  \sa SDL_TLSGet()
slouken@7391
   331
 */
slouken@11284
   332
extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void*));
slouken@7391
   333
slouken@0
   334
slouken@0
   335
/* Ends C function definitions when using C++ */
slouken@0
   336
#ifdef __cplusplus
slouken@0
   337
}
slouken@0
   338
#endif
slouken@0
   339
#include "close_code.h"
slouken@0
   340
slouken@10638
   341
#endif /* SDL_thread_h_ */
slouken@1895
   342
slouken@1895
   343
/* vi: set ts=4 sw=4 expandtab: */