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