|
| 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_ */ |
0 commit comments