1 | #ifndef Py_INTERNAL_CONDVAR_H |
2 | #define Py_INTERNAL_CONDVAR_H |
3 | |
4 | #ifndef Py_BUILD_CORE |
5 | # error "this header requires Py_BUILD_CORE define" |
6 | #endif |
7 | |
8 | #ifndef _POSIX_THREADS |
9 | /* This means pthreads are not implemented in libc headers, hence the macro |
10 | not present in unistd.h. But they still can be implemented as an external |
11 | library (e.g. gnu pth in pthread emulation) */ |
12 | # ifdef HAVE_PTHREAD_H |
13 | # include <pthread.h> /* _POSIX_THREADS */ |
14 | # endif |
15 | #endif |
16 | |
17 | #ifdef _POSIX_THREADS |
18 | /* |
19 | * POSIX support |
20 | */ |
21 | #define Py_HAVE_CONDVAR |
22 | |
23 | #include <pthread.h> |
24 | |
25 | #define PyMUTEX_T pthread_mutex_t |
26 | #define PyCOND_T pthread_cond_t |
27 | |
28 | #elif defined(NT_THREADS) |
29 | /* |
30 | * Windows (XP, 2003 server and later, as well as (hopefully) CE) support |
31 | * |
32 | * Emulated condition variables ones that work with XP and later, plus |
33 | * example native support on VISTA and onwards. |
34 | */ |
35 | #define Py_HAVE_CONDVAR |
36 | |
37 | /* include windows if it hasn't been done before */ |
38 | #define WIN32_LEAN_AND_MEAN |
39 | #include <windows.h> |
40 | |
41 | /* options */ |
42 | /* non-emulated condition variables are provided for those that want |
43 | * to target Windows Vista. Modify this macro to enable them. |
44 | */ |
45 | #ifndef _PY_EMULATED_WIN_CV |
46 | #define _PY_EMULATED_WIN_CV 1 /* use emulated condition variables */ |
47 | #endif |
48 | |
49 | /* fall back to emulation if not targeting Vista */ |
50 | #if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA |
51 | #undef _PY_EMULATED_WIN_CV |
52 | #define _PY_EMULATED_WIN_CV 1 |
53 | #endif |
54 | |
55 | #if _PY_EMULATED_WIN_CV |
56 | |
57 | typedef CRITICAL_SECTION PyMUTEX_T; |
58 | |
59 | /* The ConditionVariable object. From XP onwards it is easily emulated |
60 | with a Semaphore. |
61 | Semaphores are available on Windows XP (2003 server) and later. |
62 | We use a Semaphore rather than an auto-reset event, because although |
63 | an auto-resent event might appear to solve the lost-wakeup bug (race |
64 | condition between releasing the outer lock and waiting) because it |
65 | maintains state even though a wait hasn't happened, there is still |
66 | a lost wakeup problem if more than one thread are interrupted in the |
67 | critical place. A semaphore solves that, because its state is |
68 | counted, not Boolean. |
69 | Because it is ok to signal a condition variable with no one |
70 | waiting, we need to keep track of the number of |
71 | waiting threads. Otherwise, the semaphore's state could rise |
72 | without bound. This also helps reduce the number of "spurious wakeups" |
73 | that would otherwise happen. |
74 | */ |
75 | |
76 | typedef struct _PyCOND_T |
77 | { |
78 | HANDLE sem; |
79 | int waiting; /* to allow PyCOND_SIGNAL to be a no-op */ |
80 | } PyCOND_T; |
81 | |
82 | #else /* !_PY_EMULATED_WIN_CV */ |
83 | |
84 | /* Use native Win7 primitives if build target is Win7 or higher */ |
85 | |
86 | /* SRWLOCK is faster and better than CriticalSection */ |
87 | typedef SRWLOCK PyMUTEX_T; |
88 | |
89 | typedef CONDITION_VARIABLE PyCOND_T; |
90 | |
91 | #endif /* _PY_EMULATED_WIN_CV */ |
92 | |
93 | #endif /* _POSIX_THREADS, NT_THREADS */ |
94 | |
95 | #endif /* Py_INTERNAL_CONDVAR_H */ |
96 | |