| #ifndef Py_INTERNAL_CONDVAR_H | |
| #define Py_INTERNAL_CONDVAR_H | |
| #ifndef _POSIX_THREADS | |
| /* This means pthreads are not implemented in libc headers, hence the macro | |
| not present in unistd.h. But they still can be implemented as an external | |
| library (e.g. gnu pth in pthread emulation) */ | |
| # ifdef HAVE_PTHREAD_H | |
| # include <pthread.h> /* _POSIX_THREADS */ | |
| # endif | |
| #endif | |
| #ifdef _POSIX_THREADS | |
| /* | |
| * POSIX support | |
| */ | |
| #define Py_HAVE_CONDVAR | |
| #include <pthread.h> | |
| #define PyMUTEX_T pthread_mutex_t | |
| #define PyCOND_T pthread_cond_t | |
| #elif defined(NT_THREADS) | |
| /* | |
| * Windows (XP, 2003 server and later, as well as (hopefully) CE) support | |
| * | |
| * Emulated condition variables ones that work with XP and later, plus | |
| * example native support on VISTA and onwards. | |
| */ | |
| #define Py_HAVE_CONDVAR | |
| /* include windows if it hasn't been done before */ | |
| #define WIN32_LEAN_AND_MEAN | |
| #include <windows.h> | |
| /* options */ | |
| /* non-emulated condition variables are provided for those that want | |
| * to target Windows Vista. Modify this macro to enable them. | |
| */ | |
| #ifndef _PY_EMULATED_WIN_CV | |
| #define _PY_EMULATED_WIN_CV 1 /* use emulated condition variables */ | |
| #endif | |
| /* fall back to emulation if not targeting Vista */ | |
| #if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA | |
| #undef _PY_EMULATED_WIN_CV | |
| #define _PY_EMULATED_WIN_CV 1 | |
| #endif | |
| #if _PY_EMULATED_WIN_CV | |
| typedef CRITICAL_SECTION PyMUTEX_T; | |
| /* The ConditionVariable object. From XP onwards it is easily emulated | |
| with a Semaphore. | |
| Semaphores are available on Windows XP (2003 server) and later. | |
| We use a Semaphore rather than an auto-reset event, because although | |
| an auto-resent event might appear to solve the lost-wakeup bug (race | |
| condition between releasing the outer lock and waiting) because it | |
| maintains state even though a wait hasn't happened, there is still | |
| a lost wakeup problem if more than one thread are interrupted in the | |
| critical place. A semaphore solves that, because its state is | |
| counted, not Boolean. | |
| Because it is ok to signal a condition variable with no one | |
| waiting, we need to keep track of the number of | |
| waiting threads. Otherwise, the semaphore's state could rise | |
| without bound. This also helps reduce the number of "spurious wakeups" | |
| that would otherwise happen. | |
| */ | |
| typedef struct _PyCOND_T | |
| { | |
| HANDLE sem; | |
| int waiting; /* to allow PyCOND_SIGNAL to be a no-op */ | |
| } PyCOND_T; | |
| #else /* !_PY_EMULATED_WIN_CV */ | |
| /* Use native Win7 primitives if build target is Win7 or higher */ | |
| /* SRWLOCK is faster and better than CriticalSection */ | |
| typedef SRWLOCK PyMUTEX_T; | |
| typedef CONDITION_VARIABLE PyCOND_T; | |
| #endif /* _PY_EMULATED_WIN_CV */ | |
| #endif /* _POSIX_THREADS, NT_THREADS */ | |
| #endif /* Py_INTERNAL_CONDVAR_H */ |