GNU libmicrohttpd 1.0.2
Loading...
Searching...
No Matches
mhd_threads.h
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2016-2023 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
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#elif defined(HAVE_STDLIB_H)
43# include <stdlib.h> /* for size_t */
44#else /* ! HAVE_STDLIB_H */
45# include <stdio.h> /* for size_t */
46#endif /* ! HAVE_STDLIB_H */
47
48#if defined(MHD_USE_POSIX_THREADS)
49# undef HAVE_CONFIG_H
50# include <pthread.h>
51# define HAVE_CONFIG_H 1
52# ifndef MHD_USE_THREADS
53# define MHD_USE_THREADS 1
54# endif
55#elif defined(MHD_USE_W32_THREADS)
56# ifndef WIN32_LEAN_AND_MEAN
57# define WIN32_LEAN_AND_MEAN 1
58# endif /* !WIN32_LEAN_AND_MEAN */
59# include <windows.h>
60# ifndef MHD_USE_THREADS
61# define MHD_USE_THREADS 1
62# endif
63#else
64# error No threading API is available.
65#endif
66
67#ifdef HAVE_STDBOOL_H
68# include <stdbool.h>
69#endif /* HAVE_STDBOOL_H */
70
71#if defined(MHD_USE_POSIX_THREADS) && defined(MHD_USE_W32_THREADS)
72# error Both MHD_USE_POSIX_THREADS and MHD_USE_W32_THREADS are defined
73#endif /* MHD_USE_POSIX_THREADS && MHD_USE_W32_THREADS */
74
75#ifndef MHD_NO_THREAD_NAMES
76# if defined(MHD_USE_POSIX_THREADS)
77# if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
78 defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \
79 defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || \
80 defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \
81 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \
82 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
83# define MHD_USE_THREAD_NAME_
84# endif /* HAVE_PTHREAD_SETNAME_NP */
85# elif defined(MHD_USE_W32_THREADS)
86# ifdef _MSC_FULL_VER
87/* Thread names only available with VC compiler */
88# define MHD_USE_THREAD_NAME_
89# endif /* _MSC_FULL_VER */
90# endif
91#endif
92
93/* ** Thread handle - used to control the thread ** */
94
95#if defined(MHD_USE_POSIX_THREADS)
101# define MHD_join_thread_(native_handle) \
102 (! pthread_join ((native_handle), NULL))
103#elif defined(MHD_USE_W32_THREADS)
109# define MHD_join_thread_(native_handle) \
110 ( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \
111 (CloseHandle ( (native_handle)), ! 0) : 0 )
112#endif
113
114#if defined(MHD_USE_POSIX_THREADS)
118typedef pthread_t MHD_thread_handle_native_;
119#elif defined(MHD_USE_W32_THREADS)
123typedef HANDLE MHD_thread_handle_native_;
124#endif
125
126#if defined(MHD_USE_POSIX_THREADS)
127# if defined(__gnu_linux__) || \
128 (defined(__linux__) && defined(__GLIBC__))
129/* The next part of code is disabled because it relies on undocumented
130 behaviour.
131 It could be enabled for neglectable performance and size improvements. */
132# if 0 /* Disabled code */
136# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
137 ((MHD_thread_handle_native_) 0)
138# endif /* Disabled code */
139# endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */
140#elif defined(MHD_USE_W32_THREADS)
144# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
145 ((MHD_thread_handle_native_) NULL)
146#endif /* MHD_USE_W32_THREADS */
147
148#if ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
153{
154 bool valid;
155 MHD_thread_handle_native_ native;
156};
157
161
165# define MHD_thread_handle_set_invalid_(handle_ptr) \
166 ((handle_ptr)->valid = false)
167
171# define MHD_thread_handle_set_native_(handle_ptr,native_val) \
172 ((handle_ptr)->valid = true, (handle_ptr)->native = native_val)
173
176# define MHD_thread_handle_is_valid_(handle_var) \
177 ((handle_var).valid)
178
181# define MHD_thread_handle_get_native_(handle_var) \
182 ((handle_var).native)
183#else /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
187typedef MHD_thread_handle_native_ MHD_thread_handle_;
188
192# define MHD_thread_handle_set_invalid_(handle_ptr) \
193 ((*(handle_ptr)) = MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
198# define MHD_thread_handle_set_native_(handle_ptr,native_val) \
199 ((*(handle_ptr)) = native_val)
203# define MHD_thread_handle_is_valid_(handle_var) \
204 (MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ != handle_var)
208# define MHD_thread_handle_get_native_(handle_var) \
209 (handle_var)
215# define MHD_thread_handle_get_native_ptr_(handle_ptr) \
216 (handle_ptr)
217#endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
218
219
220/* ** Thread ID - used to check threads match ** */
221
222#if defined(MHD_USE_POSIX_THREADS)
226typedef pthread_t MHD_thread_ID_native_;
227
231# define MHD_thread_ID_native_current_ pthread_self
232
237# define MHD_thread_ID_native_equal_(id1,id2) \
238 (pthread_equal(id1,id2))
239#elif defined(MHD_USE_W32_THREADS)
243typedef DWORD MHD_thread_ID_native_;
244
248# define MHD_thread_ID_native_current_ GetCurrentThreadId
249
254# define MHD_thread_ID_native_equal_(id1,id2) \
255 ((id1) == (id2))
256#endif
257
263#define MHD_thread_ID_native_is_current_thread_(id) \
264 MHD_thread_ID_native_equal_(id, MHD_thread_ID_native_current_())
265
266
267#if defined(MHD_USE_POSIX_THREADS)
268# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
272# define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
273 MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
274# endif /* MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ */
275#elif defined(MHD_USE_W32_THREADS)
279 # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
280 ((MHD_thread_ID_native_) 0)
281#endif /* MHD_USE_W32_THREADS */
282
283#if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
288{
289 bool valid;
290 MHD_thread_ID_native_ native;
291};
292
296
300# define MHD_thread_ID_set_invalid_(ID_ptr) \
301 ((ID_ptr)->valid = false)
302
306# define MHD_thread_ID_set_native_(ID_ptr,native_val) \
307 ((ID_ptr)->valid = true, (ID_ptr)->native = native_val)
308
311# define MHD_thread_ID_is_valid_(ID_var) \
312 ((ID_var).valid)
313
316# define MHD_thread_ID_get_native_(ID_var) \
317 ((ID_var).native)
318
321# define MHD_thread_ID_is_current_thread_(ID_var) \
322 (MHD_thread_ID_is_valid_(ID_var) && \
323 MHD_thread_ID_native_is_current_thread_((ID_var).native))
324#else /* MHD_THREAD_ID_NATIVE_INVALID_ */
328typedef MHD_thread_ID_native_ MHD_thread_ID_;
329
333# define MHD_thread_ID_set_invalid_(ID_ptr) \
334 ((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
339# define MHD_thread_ID_set_native_(ID_ptr,native_val) \
340 ((*(ID_ptr)) = native_val)
344# define MHD_thread_ID_is_valid_(ID_var) \
345 (MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != ID_var)
349# define MHD_thread_ID_get_native_(ID_var) \
350 (ID_var)
354# define MHD_thread_ID_is_current_thread_(ID_var) \
355 MHD_thread_ID_native_is_current_thread_(ID_var)
356#endif /* MHD_THREAD_ID_NATIVE_INVALID_ */
357
361# define MHD_thread_ID_set_current_thread_(ID_ptr) \
362 MHD_thread_ID_set_native_(ID_ptr,MHD_thread_ID_native_current_())
363
364
365#if defined(MHD_USE_POSIX_THREADS)
366# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
367 ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
368# error \
369 MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined
370# elif ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
371 defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
372# error \
373 MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined
374# endif
375#endif /* MHD_USE_POSIX_THREADS */
376
377/* When staring a new thread, the kernel (and thread implementation) may
378 * pause the calling (initial) thread and start the new thread.
379 * If thread identifier is assigned to variable in the initial thread then
380 * the value of the identifier variable will be undefined in the new thread
381 * until the initial thread continue processing.
382 * However, it is also possible that the new thread created, but not executed
383 * for some time while the initial thread continue execution. In this case any
384 * variable assigned in the new thread will be undefined for some time until
385 * they really processed by the new thread.
386 * To avoid data races, a special structure MHD_thread_handle_ID_ is used.
387 * The "handle" is assigned by calling (initial) thread and should be always
388 * defined when checked in the initial thread.
389 * The "ID" is assigned by the new thread and should be always defined when
390 * checked inside the new thread.
391 */
392/* Depending on implementation, pthread_create() MAY set thread ID into
393 * provided pointer and after it start thread OR start thread and after
394 * it set thread ID. In the latter case, to avoid data races, additional
395 * pthread_self() call is required in thread routine. If some platform
396 * is known for setting thread ID BEFORE starting thread macro
397 * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined
398 * to save some resources. */
399/* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */
400
401/* * handle - must be valid when other thread knows that particular thread
402 is started.
403 * ID - must be valid when code is executed inside thread */
404#if defined(MHD_USE_POSIX_THREADS) && \
405 defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \
406 defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
407 defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \
408 defined(MHD_thread_handle_get_native_ptr_)
410{
413};
415# define MHD_THREAD_HANDLE_ID_IS_UNION 1
416#else /* !MHD_USE_POSIX_THREADS
417 || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
418 || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
419 || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
420 || !MHD_thread_handle_get_native_ptr_ */
427#endif /* !MHD_USE_POSIX_THREADS
428 || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
429 || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
430 || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
431 || !MHD_thread_handle_get_native_ptr_ */
432
436#define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr) \
437 (MHD_thread_handle_set_invalid_(&((hndl_id_ptr)->handle)), \
438 MHD_thread_ID_set_invalid_(&((hndl_id_ptr)->ID)))
439
444#define MHD_thread_handle_ID_is_valid_handle_(hndl_id) \
445 MHD_thread_handle_is_valid_((hndl_id).handle)
446
451#define MHD_thread_handle_ID_set_native_handle_(hndl_id_ptr,native_val) \
452 MHD_thread_handle_set_native_(&((hndl_id_ptr)->handle),native_val)
453
454#if defined(MHD_thread_handle_get_native_ptr_)
460# define MHD_thread_handle_ID_get_native_handle_ptr_(hndl_id_ptr) \
461 MHD_thread_handle_get_native_ptr_(&((hndl_id_ptr)->handle))
462#endif /* MHD_thread_handle_get_native_ptr_ */
463
467#define MHD_thread_handle_ID_get_native_handle_(hndl_id) \
468 MHD_thread_handle_get_native_((hndl_id).handle)
469
474#define MHD_thread_handle_ID_is_valid_ID_(hndl_id) \
475 MHD_thread_ID_is_valid_((hndl_id).ID)
476
477#if defined(MHD_THREAD_HANDLE_ID_IS_UNION)
478# if defined(MHD_USE_W32_THREADS)
479# error MHD_thread_handle_ID_ cannot be a union with W32 threads
480# endif /* MHD_USE_W32_THREADS */
484# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) (void) 0
485#else /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
489# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) \
490 MHD_thread_ID_set_current_thread_(&((hndl_id_ptr)->ID))
491#endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
492
498#define MHD_thread_handle_ID_is_current_thread_(hndl_id) \
499 MHD_thread_ID_is_current_thread_((hndl_id).ID)
500
506#define MHD_thread_handle_ID_join_thread_(hndl_id) \
507 MHD_join_thread_(MHD_thread_handle_ID_get_native_handle_(hndl_id))
508
509#if defined(MHD_USE_POSIX_THREADS)
510# define MHD_THRD_RTRN_TYPE_ void*
511# define MHD_THRD_CALL_SPEC_
512#elif defined(MHD_USE_W32_THREADS)
513# define MHD_THRD_RTRN_TYPE_ unsigned
514# define MHD_THRD_CALL_SPEC_ __stdcall
515#endif
516
523typedef MHD_THRD_RTRN_TYPE_
524(MHD_THRD_CALL_SPEC_ *MHD_THREAD_START_ROUTINE_)(void *cls);
525
526
538int
540 size_t stack_size,
541 MHD_THREAD_START_ROUTINE_ start_routine,
542 void *arg);
543
544#ifndef MHD_USE_THREAD_NAME_
545#define MHD_create_named_thread_(t,n,s,r,a) MHD_create_thread_ ((t),(s),(r),(a))
546#else /* MHD_USE_THREAD_NAME_ */
557int
559 const char *thread_name,
560 size_t stack_size,
561 MHD_THREAD_START_ROUTINE_ start_routine,
562 void *arg);
563
564#endif /* MHD_USE_THREAD_NAME_ */
565
566#endif /* ! MHD_THREADS_H */
additional automatic macros for MHD_config.h
struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_
struct MHD_thread_handle_struct_ MHD_thread_handle_
int MHD_create_thread_(MHD_thread_handle_ID_ *handle_id, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, void *arg)
struct MHD_thread_ID_struct_ MHD_thread_ID_
MHD_THRD_RTRN_TYPE_(MHD_THRD_CALL_SPEC_ * MHD_THREAD_START_ROUTINE_)(void *cls)
#define MHD_create_named_thread_(t, n, s, r, a)
MHD_thread_ID_native_ native
MHD_thread_handle_native_ native
MHD_thread_handle_ handle