1009b811d678f36cf63be4fe26f3fbaa38aa0078eSerhiy Storchaka/*
2e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * Portable condition variable support for windows and pthreads.
3e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * Everything is inline, this header can be included where needed.
4e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson *
5e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * APIs generally return 0 on success and non-zero on error,
6e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * and the caller needs to use its platform's error mechanism to
7e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * discover the error (errno, or GetLastError())
8e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson *
9e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * Note that some implementations cannot distinguish between a
10e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * condition variable wait time-out and successful wait. Most often
11e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * the difference is moot anyway since the wait condition must be
12e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * re-checked.
13e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * PyCOND_TIMEDWAIT, in addition to returning negative on error,
14e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * thus returns 0 on regular success, 1 on timeout
15e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * or 2 if it can't tell.
160006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *
170006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson * There are at least two caveats with using these condition variables,
180006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson * due to the fact that they may be emulated with Semaphores on
190006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson * Windows:
200006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson * 1) While PyCOND_SIGNAL() will wake up at least one thread, we
210006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    cannot currently guarantee that it will be one of the threads
220006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    already waiting in a PyCOND_WAIT() call.  It _could_ cause
230006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    the wakeup of a subsequent thread to try a PyCOND_WAIT(),
240006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    including the thread doing the PyCOND_SIGNAL() itself.
250006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    The same applies to PyCOND_BROADCAST(), if N threads are waiting
260006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    then at least N threads will be woken up, but not necessarily
270006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    those already waiting.
280006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    For this reason, don't make the scheduling assumption that a
290006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    specific other thread will get the wakeup signal
300006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson * 2) The _mutex_ must be held when calling PyCOND_SIGNAL() and
310006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    PyCOND_BROADCAST().
320006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    While e.g. the posix standard strongly recommends that the mutex
330006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    associated with the condition variable is held when a
340006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    pthread_cond_signal() call is made, this is not a hard requirement,
350006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    although scheduling will not be "reliable" if it isn't.  Here
360006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    the mutex is used for internal synchronization of the emulated
370006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson *    Condition Variable.
38e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
39e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
40e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#ifndef _CONDVAR_H_
41e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define _CONDVAR_H_
42e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
43e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#include "Python.h"
44e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
45e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#ifndef _POSIX_THREADS
46e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* This means pthreads are not implemented in libc headers, hence the macro
47e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   not present in unistd.h. But they still can be implemented as an external
48e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   library (e.g. gnu pth in pthread emulation) */
49e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson# ifdef HAVE_PTHREAD_H
50e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#  include <pthread.h> /* _POSIX_THREADS */
51e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson# endif
52e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif
53e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
54e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#ifdef _POSIX_THREADS
55e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/*
56e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * POSIX support
57e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
58e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define Py_HAVE_CONDVAR
59e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
60e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#include <pthread.h>
61e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
62e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_ADD_MICROSECONDS(tv, interval) \
6333096fe8296b57c6e634e58af1c632b8e2f5bc05Kristján Valur Jónssondo { /* TODO: add overflow and truncation checks */ \
64e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    tv.tv_usec += (long) interval; \
65e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    tv.tv_sec += tv.tv_usec / 1000000; \
66e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    tv.tv_usec %= 1000000; \
67e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson} while (0)
68e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
69e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* We assume all modern POSIX systems have gettimeofday() */
70e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#ifdef GETTIMEOFDAY_NO_TZ
71e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_GETTIMEOFDAY(ptv) gettimeofday(ptv)
72e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#else
73e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL)
74e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif
75e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
76e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* The following functions return 0 on success, nonzero on error */
77e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyMUTEX_T pthread_mutex_t
78e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyMUTEX_INIT(mut)       pthread_mutex_init((mut), NULL)
79e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyMUTEX_FINI(mut)       pthread_mutex_destroy(mut)
80e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyMUTEX_LOCK(mut)       pthread_mutex_lock(mut)
81e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyMUTEX_UNLOCK(mut)     pthread_mutex_unlock(mut)
82e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
83e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_T pthread_cond_t
84e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_INIT(cond)       pthread_cond_init((cond), NULL)
85e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_FINI(cond)       pthread_cond_destroy(cond)
86e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_SIGNAL(cond)     pthread_cond_signal(cond)
87e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_BROADCAST(cond)  pthread_cond_broadcast(cond)
88e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define PyCOND_WAIT(cond, mut)  pthread_cond_wait((cond), (mut))
89e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
90e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* return 0 for success, 1 on timeout, -1 on error */
91e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
92af580dff4af3cb812cdd7a229a4a65059b3bc1eeBenjamin PetersonPyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)
93e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
94e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    int r;
95e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    struct timespec ts;
96e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    struct timeval deadline;
97e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
98e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    PyCOND_GETTIMEOFDAY(&deadline);
99e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    PyCOND_ADD_MICROSECONDS(deadline, us);
100e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    ts.tv_sec = deadline.tv_sec;
101e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    ts.tv_nsec = deadline.tv_usec * 1000;
102e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
103e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    r = pthread_cond_timedwait((cond), (mut), &ts);
104e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    if (r == ETIMEDOUT)
105e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        return 1;
106e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    else if (r)
107e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        return -1;
108009b811d678f36cf63be4fe26f3fbaa38aa0078eSerhiy Storchaka    else
109e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        return 0;
110e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
111e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
112e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#elif defined(NT_THREADS)
113e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/*
114e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * Windows (XP, 2003 server and later, as well as (hopefully) CE) support
115e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson *
116e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * Emulated condition variables ones that work with XP and later, plus
117e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * example native support on VISTA and onwards.
118e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
119e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define Py_HAVE_CONDVAR
120e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
121e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
122e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* include windows if it hasn't been done before */
123e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define WIN32_LEAN_AND_MEAN
124e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#include <windows.h>
125e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
126e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* options */
127e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* non-emulated condition variables are provided for those that want
128e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * to target Windows Vista.  Modify this macro to enable them.
129e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
130e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#ifndef _PY_EMULATED_WIN_CV
131e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define _PY_EMULATED_WIN_CV 1  /* use emulated condition variables */
132e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif
133e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
134e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* fall back to emulation if not targeting Vista */
135e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA
136e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#undef _PY_EMULATED_WIN_CV
137e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#define _PY_EMULATED_WIN_CV 1
138e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif
139e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
140e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
141e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#if _PY_EMULATED_WIN_CV
142e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
143e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* The mutex is a CriticalSection object and
144e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   The condition variables is emulated with the help of a semaphore.
145e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   Semaphores are available on Windows XP (2003 server) and later.
146e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   We use a Semaphore rather than an auto-reset event, because although
147e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   an auto-resent event might appear to solve the lost-wakeup bug (race
148e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   condition between releasing the outer lock and waiting) because it
149e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   maintains state even though a wait hasn't happened, there is still
150e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   a lost wakeup problem if more than one thread are interrupted in the
151e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   critical place.  A semaphore solves that, because its state is counted,
152e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   not Boolean.
153e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   Because it is ok to signal a condition variable with no one
154e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   waiting, we need to keep track of the number of
155e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   waiting threads.  Otherwise, the semaphore's state could rise
156e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   without bound.  This also helps reduce the number of "spurious wakeups"
157e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   that would otherwise happen.
158e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
1590006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson   This implementation still has the problem that the threads woken
1600006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson   with a "signal" aren't necessarily those that are already
1610006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson   waiting.  It corresponds to listing 2 in:
1620006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson   http://birrell.org/andrew/papers/ImplementingCVs.pdf
1630006aacb9dda6d62013c86aac47d977b3f04921aKristjan Valur Jonsson
164e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   Generic emulations of the pthread_cond_* API using
165e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   earlier Win32 functions can be found on the Web.
16632ecccaf632ba1219734249f528a451076290386Kristján Valur Jónsson   The following read can be give background information to these issues,
16732ecccaf632ba1219734249f528a451076290386Kristján Valur Jónsson   but the implementations are all broken in some way.
168e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson   http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
169e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson*/
170e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
171e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónssontypedef CRITICAL_SECTION PyMUTEX_T;
172e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
173e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
174e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_INIT(PyMUTEX_T *cs)
175e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
176e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    InitializeCriticalSection(cs);
177e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
178e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
179e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
180e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
181e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_FINI(PyMUTEX_T *cs)
182e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
183e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    DeleteCriticalSection(cs);
184e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
185e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
186e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
187e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
188e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_LOCK(PyMUTEX_T *cs)
189e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
190e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    EnterCriticalSection(cs);
191e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
192e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
193e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
194e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
195e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_UNLOCK(PyMUTEX_T *cs)
196e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
197e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    LeaveCriticalSection(cs);
198e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
199e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
200e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
201e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* The ConditionVariable object.  From XP onwards it is easily emulated with
202e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * a Semaphore
203e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
204e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
205e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónssontypedef struct _PyCOND_T
206e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
207e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    HANDLE sem;
2081617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson    int waiting; /* to allow PyCOND_SIGNAL to be a no-op */
209e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson} PyCOND_T;
210e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
211e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
212e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_INIT(PyCOND_T *cv)
213e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
214e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    /* A semaphore with a "large" max value,  The positive value
215e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     * is only needed to catch those "lost wakeup" events and
216e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     * race conditions when a timed wait elapses.
217e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     */
218e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    cv->sem = CreateSemaphore(NULL, 0, 100000, NULL);
219e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    if (cv->sem==NULL)
220e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        return -1;
221e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    cv->waiting = 0;
222e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
223e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
224e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
225e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
226e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_FINI(PyCOND_T *cv)
227e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
228e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return CloseHandle(cv->sem) ? 0 : -1;
229e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
230e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
231e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* this implementation can detect a timeout.  Returns 1 on timeout,
232e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * 0 otherwise (and -1 on error)
233e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
234e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
235e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson_PyCOND_WAIT_MS(PyCOND_T *cv, PyMUTEX_T *cs, DWORD ms)
236e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
237e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    DWORD wait;
238e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    cv->waiting++;
239e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    PyMUTEX_UNLOCK(cs);
240e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    /* "lost wakeup bug" would occur if the caller were interrupted here,
24115f44ab043b37c064d6891c7864205fed9fb0dd1Raymond Hettinger     * but we are safe because we are using a semaphore which has an internal
242e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     * count.
243e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     */
244b26a9b10ea5f095da0c699e41b29a724021cd09aMartin v. Löwis    wait = WaitForSingleObjectEx(cv->sem, ms, FALSE);
245e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    PyMUTEX_LOCK(cs);
246e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    if (wait != WAIT_OBJECT_0)
247e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        --cv->waiting;
248e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        /* Here we have a benign race condition with PyCOND_SIGNAL.
249e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson         * When failure occurs or timeout, it is possible that
250e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson         * PyCOND_SIGNAL also decrements this value
251e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson         * and signals releases the mutex.  This is benign because it
252e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson         * just means an extra spurious wakeup for a waiting thread.
2531617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson         * ('waiting' corresponds to the semaphore's "negative" count and
2541617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson         * we may end up with e.g. (waiting == -1 && sem.count == 1).  When
2551617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson         * a new thread comes along, it will pass right throuhgh, having
2561617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson         * adjusted it to (waiting == 0 && sem.count == 0).
257e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson         */
258009b811d678f36cf63be4fe26f3fbaa38aa0078eSerhiy Storchaka
259e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    if (wait == WAIT_FAILED)
260e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        return -1;
261e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    /* return 0 on success, 1 on timeout */
262e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return wait != WAIT_OBJECT_0;
263e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
264e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
265e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
266e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
267e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
268e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    int result = _PyCOND_WAIT_MS(cv, cs, INFINITE);
269e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return result >= 0 ? 0 : result;
270e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
271e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
272e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
273af580dff4af3cb812cdd7a229a4a65059b3bc1eeBenjamin PetersonPyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
274e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
27533096fe8296b57c6e634e58af1c632b8e2f5bc05Kristján Valur Jónsson    return _PyCOND_WAIT_MS(cv, cs, (DWORD)(us/1000));
276e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
277e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
278e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
279e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_SIGNAL(PyCOND_T *cv)
280e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
2811617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson    /* this test allows PyCOND_SIGNAL to be a no-op unless required
2821617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson     * to wake someone up, thus preventing an unbounded increase of
2831617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson     * the semaphore's internal counter.
2841617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson     */
2851617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson    if (cv->waiting > 0) {
286e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        /* notifying thread decreases the cv->waiting count so that
2871617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson         * a delay between notify and actual wakeup of the target thread
2881617077bccc4ff0c3d54d066af4c3cfd532cf3faKristjan Valur Jonsson         * doesn't cause a number of extra ReleaseSemaphore calls.
289e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson         */
290e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        cv->waiting--;
291e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson        return ReleaseSemaphore(cv->sem, 1, NULL) ? 0 : -1;
292e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    }
293e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
294e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
295e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
296e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
297e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_BROADCAST(PyCOND_T *cv)
298e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
29932ecccaf632ba1219734249f528a451076290386Kristján Valur Jónsson    int waiting = cv->waiting;
30032ecccaf632ba1219734249f528a451076290386Kristján Valur Jónsson    if (waiting > 0) {
30132ecccaf632ba1219734249f528a451076290386Kristján Valur Jónsson        cv->waiting = 0;
30232ecccaf632ba1219734249f528a451076290386Kristján Valur Jónsson        return ReleaseSemaphore(cv->sem, waiting, NULL) ? 0 : -1;
303e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    }
304e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
305e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
306e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
307e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#else
308e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
309e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* Use native Win7 primitives if build target is Win7 or higher */
310e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
311e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* SRWLOCK is faster and better than CriticalSection */
312e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónssontypedef SRWLOCK PyMUTEX_T;
313e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
314e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
315e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_INIT(PyMUTEX_T *cs)
316e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
317e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    InitializeSRWLock(cs);
318e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
319e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
320e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
321e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
322e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_FINI(PyMUTEX_T *cs)
323e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
324e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
325e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
326e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
327e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
328e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_LOCK(PyMUTEX_T *cs)
329e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
330e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    AcquireSRWLockExclusive(cs);
331e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
332e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
333e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
334e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
335e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyMUTEX_UNLOCK(PyMUTEX_T *cs)
336e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
337e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    ReleaseSRWLockExclusive(cs);
338e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
339e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
340e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
341e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
342e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónssontypedef CONDITION_VARIABLE  PyCOND_T;
343e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
344e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
345e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_INIT(PyCOND_T *cv)
346e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
347e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    InitializeConditionVariable(cv);
348e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
349e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
350e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
351e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_FINI(PyCOND_T *cv)
352e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
353e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return 0;
354e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
355e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
356e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
357e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
358e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
359e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson    return SleepConditionVariableSRW(cv, cs, INFINITE, 0) ? 0 : -1;
360e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
361e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
362e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson/* This implementation makes no distinction about timeouts.  Signal
363e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson * 2 to indicate that we don't know.
364e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson */
365e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
366af580dff4af3cb812cdd7a229a4a65059b3bc1eeBenjamin PetersonPyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
367e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
36833096fe8296b57c6e634e58af1c632b8e2f5bc05Kristján Valur Jónsson    return SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0) ? 2 : -1;
369e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
370e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
371e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
372e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_SIGNAL(PyCOND_T *cv)
373e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
374e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     WakeConditionVariable(cv);
375e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     return 0;
376e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
377e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
378e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPy_LOCAL_INLINE(int)
379e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur JónssonPyCOND_BROADCAST(PyCOND_T *cv)
380e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson{
381e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     WakeAllConditionVariable(cv);
382e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson     return 0;
383e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson}
384e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
385e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
386e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif /* _PY_EMULATED_WIN_CV */
387e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
388e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif /* _POSIX_THREADS, NT_THREADS */
389e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson
390e75ff35af2b6c85d48c68b95f295aeac7396b162Kristján Valur Jónsson#endif /* _CONDVAR_H_ */
391