diff options
Diffstat (limited to 'src/threading.h')
-rw-r--r-- | src/threading.h | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/threading.h b/src/threading.h new file mode 100644 index 0000000..4a83229 --- /dev/null +++ b/src/threading.h | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * THREADING.H | ||
3 | */ | ||
4 | #ifndef THREADING_H | ||
5 | #define THREADING_H | ||
6 | |||
7 | /* Platform detection | ||
8 | */ | ||
9 | #ifdef _WIN32_WCE | ||
10 | #define PLATFORM_POCKETPC | ||
11 | #elif (defined _WIN32) | ||
12 | #define PLATFORM_WIN32 | ||
13 | #elif (defined __linux__) | ||
14 | #define PLATFORM_LINUX | ||
15 | #elif (defined __APPLE__) && (defined __MACH__) | ||
16 | #define PLATFORM_OSX | ||
17 | #elif (defined __NetBSD__) || (defined __FreeBSD__) || (defined BSD) | ||
18 | #define PLATFORM_BSD | ||
19 | #elif (defined __QNX__) | ||
20 | #define PLATFORM_QNX | ||
21 | #elif (defined __CYGWIN__) | ||
22 | #define PLATFORM_CYGWIN | ||
23 | #else | ||
24 | #error "Unknown platform!" | ||
25 | #endif | ||
26 | |||
27 | typedef int bool_t; | ||
28 | #ifndef FALSE | ||
29 | # define FALSE 0 | ||
30 | # define TRUE 1 | ||
31 | #endif | ||
32 | |||
33 | typedef unsigned int uint_t; | ||
34 | |||
35 | #if defined(PLATFORM_WIN32) && defined(__GNUC__) | ||
36 | /* MinGW with MSVCR80.DLL */ | ||
37 | /* Do this BEFORE including time.h so that it is declaring _mktime32() | ||
38 | * as it would have declared mktime(). | ||
39 | */ | ||
40 | # define mktime _mktime32 | ||
41 | #endif | ||
42 | #include <time.h> | ||
43 | |||
44 | /* Note: ERROR is a defined entity on Win32 | ||
45 | */ | ||
46 | enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; | ||
47 | |||
48 | |||
49 | /*---=== Locks & Signals ===--- | ||
50 | */ | ||
51 | |||
52 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | ||
53 | #define WIN32_LEAN_AND_MEAN | ||
54 | // 'SignalObjectAndWait' needs this (targets Windows 2000 and above) | ||
55 | #define _WIN32_WINNT 0x0400 | ||
56 | #include <windows.h> | ||
57 | #include <process.h> | ||
58 | |||
59 | // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx | ||
60 | // | ||
61 | // CRITICAL_SECTION can be used for simple code protection. Mutexes are | ||
62 | // needed for use with the SIGNAL system. | ||
63 | // | ||
64 | #define MUTEX_T HANDLE | ||
65 | void MUTEX_INIT( MUTEX_T *ref ); | ||
66 | #define MUTEX_RECURSIVE_INIT(ref) MUTEX_INIT(ref) /* always recursive in Win32 */ | ||
67 | void MUTEX_FREE( MUTEX_T *ref ); | ||
68 | void MUTEX_LOCK( MUTEX_T *ref ); | ||
69 | void MUTEX_UNLOCK( MUTEX_T *ref ); | ||
70 | |||
71 | typedef unsigned THREAD_RETURN_T; | ||
72 | |||
73 | #define SIGNAL_T HANDLE | ||
74 | |||
75 | #define YIELD() Sleep(0) | ||
76 | #else | ||
77 | // PThread (Linux, OS X, ...) | ||
78 | // | ||
79 | #include <pthread.h> | ||
80 | |||
81 | #ifdef PLATFORM_LINUX | ||
82 | # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP | ||
83 | #else | ||
84 | /* OS X, ... */ | ||
85 | # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE | ||
86 | #endif | ||
87 | |||
88 | #define MUTEX_T pthread_mutex_t | ||
89 | #define MUTEX_INIT(ref) pthread_mutex_init(ref,NULL) | ||
90 | #define MUTEX_RECURSIVE_INIT(ref) \ | ||
91 | { pthread_mutexattr_t a; pthread_mutexattr_init( &a ); \ | ||
92 | pthread_mutexattr_settype( &a, _MUTEX_RECURSIVE ); \ | ||
93 | pthread_mutex_init(ref,&a); pthread_mutexattr_destroy( &a ); \ | ||
94 | } | ||
95 | #define MUTEX_FREE(ref) pthread_mutex_destroy(ref) | ||
96 | #define MUTEX_LOCK(ref) pthread_mutex_lock(ref) | ||
97 | #define MUTEX_UNLOCK(ref) pthread_mutex_unlock(ref) | ||
98 | |||
99 | typedef void * THREAD_RETURN_T; | ||
100 | |||
101 | typedef pthread_cond_t SIGNAL_T; | ||
102 | |||
103 | void SIGNAL_ONE( SIGNAL_T *ref ); | ||
104 | |||
105 | // Yield is non-portable: | ||
106 | // | ||
107 | // OS X 10.4.8/9 has pthread_yield_np() | ||
108 | // Linux 2.4 has pthread_yield() if _GNU_SOURCE is #defined | ||
109 | // FreeBSD 6.2 has pthread_yield() | ||
110 | // ... | ||
111 | // | ||
112 | #ifdef PLATFORM_OSX | ||
113 | #define YIELD() pthread_yield_np() | ||
114 | #else | ||
115 | #define YIELD() pthread_yield() | ||
116 | #endif | ||
117 | #endif | ||
118 | |||
119 | void SIGNAL_INIT( SIGNAL_T *ref ); | ||
120 | void SIGNAL_FREE( SIGNAL_T *ref ); | ||
121 | void SIGNAL_ALL( SIGNAL_T *ref ); | ||
122 | |||
123 | /* | ||
124 | * 'time_d': <0.0 for no timeout | ||
125 | * 0.0 for instant check | ||
126 | * >0.0 absolute timeout in secs + ms | ||
127 | */ | ||
128 | typedef double time_d; | ||
129 | time_d now_secs(void); | ||
130 | |||
131 | time_d SIGNAL_TIMEOUT_PREPARE( double rel_secs ); | ||
132 | |||
133 | bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | ||
134 | |||
135 | |||
136 | /*---=== Threading ===--- | ||
137 | */ | ||
138 | |||
139 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | ||
140 | |||
141 | typedef HANDLE THREAD_T; | ||
142 | // | ||
143 | void THREAD_CREATE( THREAD_T *ref, | ||
144 | THREAD_RETURN_T (__stdcall *func)( void * ), | ||
145 | void *data, int prio /* -3..+3 */ ); | ||
146 | |||
147 | # define THREAD_PRIO_MIN (-3) | ||
148 | # define THREAD_PRIO_MAX (+3) | ||
149 | |||
150 | #else | ||
151 | /* Platforms that have a timed 'pthread_join()' can get away with a simpler | ||
152 | * implementation. Others will use a condition variable. | ||
153 | */ | ||
154 | # ifdef USE_PTHREAD_TIMEDJOIN | ||
155 | # ifdef PLATFORM_OSX | ||
156 | # error "No 'pthread_timedjoin()' on this system" | ||
157 | # else | ||
158 | /* Linux, ... */ | ||
159 | # define PTHREAD_TIMEDJOIN pthread_timedjoin_np | ||
160 | # endif | ||
161 | # endif | ||
162 | |||
163 | typedef pthread_t THREAD_T; | ||
164 | |||
165 | void THREAD_CREATE( THREAD_T *ref, | ||
166 | THREAD_RETURN_T (*func)( void * ), | ||
167 | void *data, int prio /* -2..+2 */ ); | ||
168 | |||
169 | # if defined(PLATFORM_LINUX) | ||
170 | volatile bool_t sudo; | ||
171 | # ifdef LINUX_SCHED_RR | ||
172 | # define THREAD_PRIO_MIN (sudo ? -2 : 0) | ||
173 | # else | ||
174 | # define THREAD_PRIO_MIN (0) | ||
175 | # endif | ||
176 | # define THREAD_PRIO_MAX (sudo ? +2 : 0) | ||
177 | # else | ||
178 | # define THREAD_PRIO_MIN (-2) | ||
179 | # define THREAD_PRIO_MAX (+2) | ||
180 | # endif | ||
181 | #endif | ||
182 | |||
183 | /* | ||
184 | * Win32 and PTHREAD_TIMEDJOIN allow waiting for a thread with a timeout. | ||
185 | * Posix without PTHREAD_TIMEDJOIN needs to use a condition variable approach. | ||
186 | */ | ||
187 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) | ||
188 | bool_t THREAD_WAIT( THREAD_T *ref, double secs ); | ||
189 | #else | ||
190 | bool_t THREAD_WAIT( THREAD_T *ref, SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref, double secs ); | ||
191 | #endif | ||
192 | |||
193 | void THREAD_KILL( THREAD_T *ref ); | ||
194 | |||
195 | #endif | ||
196 | // THREADING_H | ||