Eric Snow | 2ebc5ce | 2017-09-07 23:51:28 -0600 | [diff] [blame] | 1 | #ifndef Py_INTERNAL_CONDVAR_H |
| 2 | #define Py_INTERNAL_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 /* Py_INTERNAL_CONDVAR_H */ |