diff options
Diffstat (limited to 'src/threading.h')
-rw-r--r-- | src/threading.h | 208 |
1 files changed, 56 insertions, 152 deletions
diff --git a/src/threading.h b/src/threading.h index 82c8f52..c443c82 100644 --- a/src/threading.h +++ b/src/threading.h | |||
@@ -16,22 +16,24 @@ | |||
16 | #define THREADAPI THREADAPI_PTHREAD | 16 | #define THREADAPI THREADAPI_PTHREAD |
17 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 17 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
18 | 18 | ||
19 | /*---=== Locks & Signals ===--- | 19 | static constexpr int THREAD_PRIO_DEFAULT{ -999 }; |
20 | */ | ||
21 | 20 | ||
21 | // ################################################################################################## | ||
22 | // ################################################################################################## | ||
22 | #if THREADAPI == THREADAPI_WINDOWS | 23 | #if THREADAPI == THREADAPI_WINDOWS |
23 | #if defined( PLATFORM_XBOX) | 24 | |
24 | #include <xtl.h> | 25 | #if defined(PLATFORM_XBOX) |
25 | #else // !PLATFORM_XBOX | 26 | #include <xtl.h> |
26 | #define WIN32_LEAN_AND_MEAN | 27 | #else // !PLATFORM_XBOX |
27 | // CONDITION_VARIABLE needs version 0x0600+ | 28 | #define WIN32_LEAN_AND_MEAN |
28 | // _WIN32_WINNT value is already defined by MinGW, but not by MSVC | 29 | // CONDITION_VARIABLE needs version 0x0600+ |
29 | #ifndef _WIN32_WINNT | 30 | // _WIN32_WINNT value is already defined by MinGW, but not by MSVC |
30 | #define _WIN32_WINNT 0x0600 | 31 | #ifndef _WIN32_WINNT |
31 | #endif // _WIN32_WINNT | 32 | #define _WIN32_WINNT 0x0600 |
32 | #include <windows.h> | 33 | #endif // _WIN32_WINNT |
33 | #endif // !PLATFORM_XBOX | 34 | #include <windows.h> |
34 | #include <process.h> | 35 | #endif // !PLATFORM_XBOX |
36 | #include <process.h> | ||
35 | 37 | ||
36 | /* | 38 | /* |
37 | #define XSTR(x) STR(x) | 39 | #define XSTR(x) STR(x) |
@@ -39,148 +41,50 @@ | |||
39 | #pragma message( "The value of _WIN32_WINNT: " XSTR(_WIN32_WINNT)) | 41 | #pragma message( "The value of _WIN32_WINNT: " XSTR(_WIN32_WINNT)) |
40 | */ | 42 | */ |
41 | 43 | ||
42 | // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx | 44 | static constexpr int THREAD_PRIO_MIN{ -3 }; |
43 | // | 45 | static constexpr int THREAD_PRIO_MAX{ +3 }; |
44 | // CRITICAL_SECTION can be used for simple code protection. Mutexes are | ||
45 | // needed for use with the SIGNAL system. | ||
46 | // | ||
47 | |||
48 | #if _WIN32_WINNT < 0x0600 // CONDITION_VARIABLE aren't available, use a signal | ||
49 | |||
50 | struct SIGNAL_T | ||
51 | { | ||
52 | CRITICAL_SECTION signalCS; | ||
53 | CRITICAL_SECTION countCS; | ||
54 | HANDLE waitEvent; | ||
55 | HANDLE waitDoneEvent; | ||
56 | LONG waitersCount; | ||
57 | }; | ||
58 | |||
59 | |||
60 | #else // CONDITION_VARIABLE are available, use them | ||
61 | 46 | ||
62 | #define SIGNAL_T CONDITION_VARIABLE | 47 | // ################################################################################################## |
63 | #define MUTEX_INIT( ref) InitializeCriticalSection( ref) | 48 | // ################################################################################################## |
64 | #define MUTEX_FREE( ref) DeleteCriticalSection( ref) | ||
65 | #define MUTEX_LOCK( ref) EnterCriticalSection( ref) | ||
66 | #define MUTEX_UNLOCK( ref) LeaveCriticalSection( ref) | ||
67 | |||
68 | #endif // CONDITION_VARIABLE are available | ||
69 | |||
70 | #define MUTEX_RECURSIVE_INIT(ref) MUTEX_INIT(ref) /* always recursive in Win32 */ | ||
71 | |||
72 | using THREAD_RETURN_T = unsigned int; | ||
73 | |||
74 | #define YIELD() Sleep(0) | ||
75 | #define THREAD_CALLCONV __stdcall | ||
76 | #else // THREADAPI == THREADAPI_PTHREAD | 49 | #else // THREADAPI == THREADAPI_PTHREAD |
77 | // PThread (Linux, OS X, ...) | 50 | // ################################################################################################## |
78 | 51 | // ################################################################################################## | |
79 | // looks like some MinGW installations don't support PTW32_INCLUDE_WINDOWS_H, so let's include it ourselves, just in case | 52 | |
80 | #if defined(PLATFORM_WIN32) | 53 | // PThread (Linux, OS X, ...) |
81 | #include <windows.h> | 54 | |
82 | #endif // PLATFORM_WIN32 | 55 | // looks like some MinGW installations don't support PTW32_INCLUDE_WINDOWS_H, so let's include it ourselves, just in case |
83 | #include <pthread.h> | 56 | #if defined(PLATFORM_WIN32) |
84 | 57 | #include <windows.h> | |
85 | #ifdef PLATFORM_LINUX | 58 | #endif // PLATFORM_WIN32 |
86 | #if defined(__GLIBC__) | 59 | #include <pthread.h> |
87 | # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP | 60 | |
88 | #else | 61 | // Yield is non-portable: |
89 | # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE | 62 | // |
90 | #endif | 63 | // OS X 10.4.8/9 has pthread_yield_np() |
91 | #else | 64 | // Linux 2.4 has pthread_yield() if _GNU_SOURCE is #defined |
92 | /* OS X, ... */ | 65 | // FreeBSD 6.2 has pthread_yield() |
93 | # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE | 66 | // ... |
94 | #endif | 67 | // |
95 | 68 | ||
96 | #define MUTEX_INIT(ref) pthread_mutex_init(ref, nullptr) | 69 | #if defined(PLATFORM_LINUX) |
97 | #define MUTEX_RECURSIVE_INIT(ref) \ | 70 | extern volatile bool sudo; |
98 | { pthread_mutexattr_t a; pthread_mutexattr_init( &a ); \ | 71 | # ifdef LINUX_SCHED_RR |
99 | pthread_mutexattr_settype( &a, _MUTEX_RECURSIVE ); \ | 72 | # define THREAD_PRIO_MIN (sudo ? -3 : 0) |
100 | pthread_mutex_init(ref,&a); pthread_mutexattr_destroy( &a ); \ | 73 | # else |
101 | } | 74 | static constexpr int THREAD_PRIO_MIN{ 0 }; |
102 | #define MUTEX_FREE(ref) pthread_mutex_destroy(ref) | 75 | #endif |
103 | #define MUTEX_LOCK(ref) pthread_mutex_lock(ref) | 76 | # define THREAD_PRIO_MAX (sudo ? +3 : 0) |
104 | #define MUTEX_UNLOCK(ref) pthread_mutex_unlock(ref) | 77 | #else |
105 | 78 | static constexpr int THREAD_PRIO_MIN{ -3 }; | |
106 | using THREAD_RETURN_T = void *; | 79 | static constexpr int THREAD_PRIO_MAX{ +3 }; |
107 | 80 | #endif | |
108 | using SIGNAL_T = pthread_cond_t; | ||
109 | |||
110 | // Yield is non-portable: | ||
111 | // | ||
112 | // OS X 10.4.8/9 has pthread_yield_np() | ||
113 | // Linux 2.4 has pthread_yield() if _GNU_SOURCE is #defined | ||
114 | // FreeBSD 6.2 has pthread_yield() | ||
115 | // ... | ||
116 | // | ||
117 | #if defined( PLATFORM_OSX) | ||
118 | #define YIELD() pthread_yield_np() | ||
119 | #else | ||
120 | #define YIELD() sched_yield() | ||
121 | #endif | ||
122 | #define THREAD_CALLCONV | ||
123 | #endif //THREADAPI == THREADAPI_PTHREAD | ||
124 | |||
125 | /*---=== Threading ===--- | ||
126 | */ | ||
127 | |||
128 | #define THREAD_PRIO_DEFAULT (-999) | ||
129 | |||
130 | #if THREADAPI == THREADAPI_WINDOWS | ||
131 | |||
132 | # define THREAD_PRIO_MIN (-3) | ||
133 | # define THREAD_PRIO_MAX (+3) | ||
134 | |||
135 | #else // THREADAPI == THREADAPI_PTHREAD | ||
136 | |||
137 | /* Platforms that have a timed 'pthread_join()' can get away with a simpler | ||
138 | * implementation. Others will use a condition variable. | ||
139 | */ | ||
140 | # if defined __WINPTHREADS_VERSION | ||
141 | //# define USE_PTHREAD_TIMEDJOIN | ||
142 | # endif // __WINPTHREADS_VERSION | ||
143 | |||
144 | # ifdef USE_PTHREAD_TIMEDJOIN | ||
145 | # ifdef PLATFORM_OSX | ||
146 | # error "No 'pthread_timedjoin()' on this system" | ||
147 | # else | ||
148 | /* Linux, ... */ | ||
149 | # define PTHREAD_TIMEDJOIN pthread_timedjoin_np | ||
150 | # endif | ||
151 | # endif | ||
152 | |||
153 | # if defined(PLATFORM_LINUX) | ||
154 | extern volatile bool sudo; | ||
155 | # ifdef LINUX_SCHED_RR | ||
156 | # define THREAD_PRIO_MIN (sudo ? -3 : 0) | ||
157 | # else | ||
158 | # define THREAD_PRIO_MIN (0) | ||
159 | # endif | ||
160 | # define THREAD_PRIO_MAX (sudo ? +3 : 0) | ||
161 | # else | ||
162 | # define THREAD_PRIO_MIN (-3) | ||
163 | # define THREAD_PRIO_MAX (+3) | ||
164 | # endif | ||
165 | 81 | ||
166 | #endif // THREADAPI == THREADAPI_WINDOWS | 82 | #endif // THREADAPI == THREADAPI_WINDOWS |
83 | // ################################################################################################## | ||
84 | // ################################################################################################## | ||
167 | 85 | ||
168 | /* | 86 | void THREAD_SETNAME(char const* _name); |
169 | * Win32 and PTHREAD_TIMEDJOIN allow waiting for a thread with a timeout. | 87 | void THREAD_SET_PRIORITY(int prio); |
170 | * Posix without PTHREAD_TIMEDJOIN needs to use a condition variable approach. | 88 | void THREAD_SET_AFFINITY(unsigned int aff); |
171 | */ | ||
172 | #define THREADWAIT_TIMEOUT 1 | ||
173 | #define THREADWAIT_CONDVAR 2 | ||
174 | |||
175 | #if THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) | ||
176 | #define THREADWAIT_METHOD THREADWAIT_TIMEOUT | ||
177 | #else // THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) | ||
178 | #define THREADWAIT_METHOD THREADWAIT_CONDVAR | ||
179 | #endif // THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) | ||
180 | |||
181 | |||
182 | void THREAD_SETNAME( char const* _name); | ||
183 | void THREAD_SET_PRIORITY( int prio); | ||
184 | void THREAD_SET_AFFINITY( unsigned int aff); | ||
185 | 89 | ||
186 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_); | 90 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_); |