diff options
Diffstat (limited to 'src/lib/mhd_threads.h')
-rw-r--r-- | src/lib/mhd_threads.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/src/lib/mhd_threads.h b/src/lib/mhd_threads.h new file mode 100644 index 00000000..6d69b9ed --- /dev/null +++ b/src/lib/mhd_threads.h | |||
@@ -0,0 +1,229 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2016 Karlson2k (Evgeny Grin) | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file microhttpd/mhd_threads.h | ||
23 | * @brief Header for platform-independent threads abstraction | ||
24 | * @author Karlson2k (Evgeny Grin) | ||
25 | * | ||
26 | * Provides basic abstraction for threads. | ||
27 | * Any functions can be implemented as macro on some platforms | ||
28 | * unless explicitly marked otherwise. | ||
29 | * Any function argument can be skipped in macro, so avoid | ||
30 | * variable modification in function parameters. | ||
31 | * | ||
32 | * @warning Unlike pthread functions, most of functions return | ||
33 | * nonzero on success. | ||
34 | */ | ||
35 | |||
36 | #ifndef MHD_THREADS_H | ||
37 | #define MHD_THREADS_H 1 | ||
38 | |||
39 | #include "mhd_options.h" | ||
40 | #ifdef HAVE_STDDEF_H | ||
41 | # include <stddef.h> /* for size_t */ | ||
42 | #else /* ! HAVE_STDDEF_H */ | ||
43 | # include <stdlib.h> /* for size_t */ | ||
44 | #endif /* ! HAVE_STDDEF_H */ | ||
45 | |||
46 | #if defined(MHD_USE_POSIX_THREADS) | ||
47 | # undef HAVE_CONFIG_H | ||
48 | # include <pthread.h> | ||
49 | # define HAVE_CONFIG_H 1 | ||
50 | #elif defined(MHD_USE_W32_THREADS) | ||
51 | # ifndef WIN32_LEAN_AND_MEAN | ||
52 | # define WIN32_LEAN_AND_MEAN 1 | ||
53 | # endif /* !WIN32_LEAN_AND_MEAN */ | ||
54 | # include <windows.h> | ||
55 | #else | ||
56 | # error No threading API is available. | ||
57 | #endif | ||
58 | |||
59 | #ifndef MHD_NO_THREAD_NAMES | ||
60 | # if defined(MHD_USE_POSIX_THREADS) | ||
61 | # if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \ | ||
62 | defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \ | ||
63 | defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI) | ||
64 | # define MHD_USE_THREAD_NAME_ | ||
65 | # endif /* HAVE_PTHREAD_SETNAME_NP */ | ||
66 | # elif defined(MHD_USE_W32_THREADS) | ||
67 | # ifdef _MSC_FULL_VER | ||
68 | /* Thread names only available with VC compiler */ | ||
69 | # define MHD_USE_THREAD_NAME_ | ||
70 | # endif /* _MSC_FULL_VER */ | ||
71 | # endif | ||
72 | #endif | ||
73 | |||
74 | #if defined(MHD_USE_POSIX_THREADS) | ||
75 | typedef pthread_t MHD_thread_handle_; | ||
76 | #elif defined(MHD_USE_W32_THREADS) | ||
77 | typedef HANDLE MHD_thread_handle_; | ||
78 | #endif | ||
79 | |||
80 | #if defined(MHD_USE_POSIX_THREADS) | ||
81 | # define MHD_THRD_RTRN_TYPE_ void* | ||
82 | # define MHD_THRD_CALL_SPEC_ | ||
83 | #elif defined(MHD_USE_W32_THREADS) | ||
84 | # define MHD_THRD_RTRN_TYPE_ unsigned | ||
85 | # define MHD_THRD_CALL_SPEC_ __stdcall | ||
86 | #endif | ||
87 | |||
88 | #if defined(MHD_USE_POSIX_THREADS) | ||
89 | typedef pthread_t MHD_thread_ID_; | ||
90 | #elif defined(MHD_USE_W32_THREADS) | ||
91 | typedef DWORD MHD_thread_ID_; | ||
92 | #endif | ||
93 | |||
94 | /* Depending on implementation, pthread_create() MAY set thread ID into | ||
95 | * provided pointer and after it start thread OR start thread and after | ||
96 | * if set thread ID. In latter case, to avoid data races, additional | ||
97 | * pthread_self() call is required in thread routine. Is some platform | ||
98 | * is known for setting thread ID BEFORE starting thread macro | ||
99 | * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined | ||
100 | * to save some resources. */ | ||
101 | #if defined(MHD_USE_POSIX_THREADS) | ||
102 | # ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD | ||
103 | union _MHD_thread_handle_ID_ | ||
104 | { | ||
105 | MHD_thread_handle_ handle; /**< To be used in other threads */ | ||
106 | MHD_thread_ID_ ID; /**< To be used in thread itself */ | ||
107 | }; | ||
108 | typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_; | ||
109 | # else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ | ||
110 | struct _MHD_thread_handle_ID_ | ||
111 | { | ||
112 | MHD_thread_handle_ handle; /**< To be used in other threads */ | ||
113 | MHD_thread_ID_ ID; /**< To be used in thread itself */ | ||
114 | }; | ||
115 | typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; | ||
116 | # endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ | ||
117 | #elif defined(MHD_USE_W32_THREADS) | ||
118 | struct _MHD_thread_handle_ID_ | ||
119 | { | ||
120 | MHD_thread_handle_ handle; /**< To be used in other threads */ | ||
121 | MHD_thread_ID_ ID; /**< To be used in thread itself */ | ||
122 | }; | ||
123 | typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; | ||
124 | #endif | ||
125 | |||
126 | #if defined(MHD_USE_POSIX_THREADS) | ||
127 | /** | ||
128 | * Wait until specified thread is ended and free thread handle on success. | ||
129 | * @param thread handle to watch | ||
130 | * @return nonzero on success, zero otherwise | ||
131 | */ | ||
132 | #define MHD_join_thread_(thread) (!pthread_join((thread), NULL)) | ||
133 | #elif defined(MHD_USE_W32_THREADS) | ||
134 | /** | ||
135 | * Wait until specified thread is ended and free thread handle on success. | ||
136 | * @param thread handle to watch | ||
137 | * @return nonzero on success, zero otherwise | ||
138 | */ | ||
139 | #define MHD_join_thread_(thread) (WAIT_OBJECT_0 == WaitForSingleObject((thread), INFINITE) ? (CloseHandle((thread)), !0) : 0) | ||
140 | #endif | ||
141 | |||
142 | #if defined(MHD_USE_POSIX_THREADS) | ||
143 | /** | ||
144 | * Check whether provided thread ID match current thread. | ||
145 | * @param ID thread ID to match | ||
146 | * @return nonzero on match, zero otherwise | ||
147 | */ | ||
148 | #define MHD_thread_ID_match_current_(ID) (pthread_equal((ID), pthread_self())) | ||
149 | #elif defined(MHD_USE_W32_THREADS) | ||
150 | /** | ||
151 | * Check whether provided thread ID match current thread. | ||
152 | * @param ID thread ID to match | ||
153 | * @return nonzero on match, zero otherwise | ||
154 | */ | ||
155 | #define MHD_thread_ID_match_current_(ID) (GetCurrentThreadId() == (ID)) | ||
156 | #endif | ||
157 | |||
158 | #if defined(MHD_USE_POSIX_THREADS) | ||
159 | # ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD | ||
160 | /** | ||
161 | * Initialise thread ID. | ||
162 | * @param thread_handle_ID_ptr pointer to thread handle-ID | ||
163 | */ | ||
164 | #define MHD_thread_init_(thread_handle_ID_ptr) (void)0 | ||
165 | # else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ | ||
166 | /** | ||
167 | * Initialise thread ID. | ||
168 | * @param thread_handle_ID_ptr pointer to thread handle-ID | ||
169 | */ | ||
170 | #define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID=pthread_self()) | ||
171 | # endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ | ||
172 | #elif defined(MHD_USE_W32_THREADS) | ||
173 | /** | ||
174 | * Initialise thread ID. | ||
175 | * @param thread_handle_ID_ptr pointer to thread handle-ID | ||
176 | */ | ||
177 | #define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID=GetCurrentThreadId()) | ||
178 | #endif | ||
179 | |||
180 | /** | ||
181 | * Signature of main function for a thread. | ||
182 | * | ||
183 | * @param cls closure argument for the function | ||
184 | * @return termination code from the thread | ||
185 | */ | ||
186 | typedef MHD_THRD_RTRN_TYPE_ | ||
187 | (MHD_THRD_CALL_SPEC_ *MHD_THREAD_START_ROUTINE_)(void *cls); | ||
188 | |||
189 | |||
190 | /** | ||
191 | * Create a thread and set the attributes according to our options. | ||
192 | * | ||
193 | * If thread is created, thread handle must be freed by MHD_join_thread_(). | ||
194 | * | ||
195 | * @param thread handle to initialize | ||
196 | * @param stack_size size of stack for new thread, 0 for default | ||
197 | * @param start_routine main function of thread | ||
198 | * @param arg argument for start_routine | ||
199 | * @return non-zero on success; zero otherwise | ||
200 | */ | ||
201 | int | ||
202 | MHD_create_thread_ (MHD_thread_handle_ID_ *thread, | ||
203 | size_t stack_size, | ||
204 | MHD_THREAD_START_ROUTINE_ start_routine, | ||
205 | void *arg); | ||
206 | |||
207 | #ifndef MHD_USE_THREAD_NAME_ | ||
208 | #define MHD_create_named_thread_(t,n,s,r,a) MHD_create_thread_((t),(s),(r),(a)) | ||
209 | #else /* MHD_USE_THREAD_NAME_ */ | ||
210 | /** | ||
211 | * Create a named thread and set the attributes according to our options. | ||
212 | * | ||
213 | * @param thread handle to initialize | ||
214 | * @param thread_name name for new thread | ||
215 | * @param stack_size size of stack for new thread, 0 for default | ||
216 | * @param start_routine main function of thread | ||
217 | * @param arg argument for start_routine | ||
218 | * @return non-zero on success; zero otherwise | ||
219 | */ | ||
220 | int | ||
221 | MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, | ||
222 | const char* thread_name, | ||
223 | size_t stack_size, | ||
224 | MHD_THREAD_START_ROUTINE_ start_routine, | ||
225 | void *arg); | ||
226 | |||
227 | #endif /* MHD_USE_THREAD_NAME_ */ | ||
228 | |||
229 | #endif /* ! MHD_THREADS_H */ | ||