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_ */