8000 make global flags free-threaded friendly · python/cpython@5a119c7 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5a119c7

Browse files
committed
make global flags free-threaded friendly
1 parent bd393ae commit 5a119c7

File tree

1 file changed

+146
-33
lines changed

1 file changed

+146
-33
lines changed

Modules/_cursesmodule.c

Lines changed: 146 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,118 @@ class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type"
192192
[clinic start generated code]*/
193193
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ae6cb623018f2cbc]*/
194194

195-
/* Tells whether setupterm() has been called to initialise terminfo. */
195+
/*
196+
* Tells whether setupterm() has been called to initialise terminfo.
197+
*
198+
* Use curses_setupterm_{was,set}_called() for atomic reads and writes.
199+
*/
196200
static int curses_setupterm_called = FALSE;
197201

198-
/* Tells whether initscr() has been called to initialise curses. */
202+
static inline int
203+
curses_setupterm_was_called(void)
204+
{
205+
#ifdef Py_GIL_DISABLED
206+
return _Py_atomic_load_int(&curses_setupterm_called);
207+
#else
208+
return curses_setupterm_called;
209+
#endif
210+
}
211+
212+
static inline void
213+
curses_setupterm_set_called(void)
214+
{
215+
#ifdef Py_GIL_DISABLED
216+
_Py_atomic_store_int(&curses_setupterm_called, TRUE);
217+
#else
218+
curses_setupterm_called = TRUE;
219+
#endif
220+
}
221+
222+
/*
223+
* Tells whether initscr() has been called to initialise curses.
224+
*
225+
* Use curses_initscr_{was,set}_called() for atomic reads and writes.
226+
*/
199227
static int curses_initscr_called = FALSE;
200228

201-
/* Tells whether start_color() has been called to initialise color usage. */
229+
static inline int
230+
curses_initscr_was_called(void)
231+
{
232+
#ifdef Py_GIL_DISABLED
233+
return _Py_atomic_load_int(&curses_initscr_called);
234+
#else
235+
return curses_initscr_called;
236+
#endif
237+
}
238+
239+
static inline void
240+
curses_initscr_set_called(void)
241+
{
242+
#ifdef Py_GIL_DISABLED
243+
_Py_atomic_store_int(&curses_initscr_called, TRUE);
244+
#else
245+
curses_initscr_called = TRUE;
246+
#endif
247+
}
248+
249+
/*
250+
* Tells whether start_color() has been called to initialise color usage.
251+
*
252+
* Use curses_start_color_{was,set}_called() for atomic reads and writes.
253+
*/
202254
static int curses_start_color_called = FALSE;
203255

256+
static inline int
257+
curses_start_color_was_called(void)
258+
{
259+
#ifdef Py_GIL_DISABLED
260+
return _Py_atomic_load_int(&curses_start_color_called);
261+
#else
262+
return curses_start_color_called;
263+
#endif
264+
}
265+
266+
static inline void
267+
curses_start_color_set_called(void)
268+
{
269+
#ifdef Py_GIL_DISABLED
270+
_Py_atomic_store_int(&curses_start_color_called, TRUE);
271+
#else
272+
curses_start_color_called = TRUE;
273+
#endif
274+
}
275+
276+
/*
277+
* The curses screen encoding.
278+
*
279+
* Use curses_{get,set}_screen_encoding() to
280+
* safely (atomically) access this variable.
281+
*/
204282
static const char *curses_screen_encoding = NULL;
205283

284+
/* Atomically retrieve the current screen encoding. */
285+
static inline const char *
286+
curses_get_screen_encoding(void)
287+
{
288+
#ifdef Py_GIL_DISABLED
289+
return (const char *)_Py_atomic_load_ptr(&curses_screen_encoding);
290+
#else
291+
return curses_screen_encoding;
292+
#endif
293+
}
294+
295+
/* Atomically set the current screen encoding. */
296+
static inline void
297+
curses_set_screen_encoding(const char *encoding)
298+
{
299+
assert(encoding != NULL);
300+
#ifdef Py_GIL_DISABLED
301+
_Py_atomic_store_ptr(&curses_screen_encoding, (char *)encoding);
302+
#else
303+
curses_screen_encoding = encoding;
304+
#endif
305+
}
306+
206307
/* Utility Checking Procedures */
207308

208309
/*
@@ -215,7 +316,7 @@ static const char *curses_screen_encoding = NULL;
215316
* type is directly taken from the global state for now.
216317
*/
217318
static inline int
218-
_PyCursesCheckFunction(int called, const char *funcname)
319+
_PyCursesStatelessCheckWasCalled(int called, const char *funcname)
219320
{
220321
if (called == TRUE) {
221322
return 1;
@@ -232,7 +333,7 @@ _PyCursesCheckFunction(int called, const char *funcname)
232333
* The exception type is obtained from the 'module' state.
233334
*/
234335
static inline int
235-
_PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcname)
336+
_PyCursesCheckWasCalled(PyObject *module, int called, const char *funcname)
236337
{
237338
if (called == TRUE) {
238339
return 1;
@@ -244,30 +345,24 @@ _PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcnam
244345

245346
#define PyCursesStatefulSetupTermCalled(MODULE) \
246347
do { \
247-
if (!_PyCursesStatefulCheckFunction(MODULE, \
248-
curses_setupterm_called, \
249-
"setupterm")) \
250-
{ \
348+
int called = curses_setupterm_was_called(); \
349+
if (!_PyCursesCheckWasCalled(MODULE, called, "setupterm")) { \
251350
return 0; \
252351
} \
253352
} while (0)
254353

255354
#define PyCursesStatefulInitialised(MODULE) \
256355
do { \
257-
if (!_PyCursesStatefulCheckFunction(MODULE, \
258-
curses_initscr_called, \
259-
"initscr")) \
260-
{ \
356+
int called = curses_initscr_was_called(); \
357+
if (!_PyCursesCheckWasCalled(MODULE, called, "initscr")) { \
261358
return 0; \
262359
} \
263360
} while (0)
264361

265362
#define PyCursesStatefulInitialisedColor(MODULE) \
266363
do { \
267-
if (!_PyCursesStatefulCheckFunction(MODULE, \
268-
curses_start_color_called, \
269-
"start_color")) \
270-
{ \
364+
int called = curses_start_color_was_called(); \
365+
if (!_PyCursesCheckWasCalled(MODULE, called, "start_color")) { \
271366
return 0; \
272367
} \
273368
} while (0)
@@ -350,7 +445,7 @@ PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch)
350445
if (win)
351446
encoding = win->encoding;
352447
else
353-
encoding = curses_screen_encoding;
448+
encoding = curses_get_screen_encoding();
354449
bytes = PyUnicode_AsEncodedString(obj, encoding, NULL);
355450
if (bytes == NULL)
356451
return 0;
@@ -3356,7 +3451,7 @@ _curses_initscr_impl(PyObject *module)
33563451
{
33573452
WINDOW *win;
33583453

3359-
if (curses_initscr_called) {
3454+
if (curses_initscr_was_called()) {
33603455
wrefresh(stdscr);
33613456
_cursesmodule_state *state = get_cursesmodule_state(module);
33623457
return PyCursesWindow_New(state, stdscr, NULL);
@@ -3370,7 +3465,8 @@ _curses_initscr_impl(PyObject *module)
33703465
return NULL;
33713466
}
33723467

3373-
curses_initscr_called = curses_setupterm_called = TRUE;
3468+
curses_initscr_set_called();
3469+
curses_setupterm_set_called();
33743470

33753471
PyObject *module_dict = PyModule_GetDict(module); // borrowed
33763472
if (module_dict == NULL) {
@@ -3467,7 +3563,7 @@ _curses_initscr_impl(PyObject *module)
34673563
if (winobj == NULL) {
34683564
return NULL;
34693565
}
3470-
curses_screen_encoding = ((PyCursesWindowObject *)winobj)->encoding;
3566+
curses_set_screen_encoding(((PyCursesWindowObject *)winobj)->encoding);
34713567
return winobj;
34723568
}
34733569

@@ -3522,8 +3618,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd)
35223618
return NULL;
35233619
}
35243620

3525-
curses_setupterm_called = TRUE;
3526-
3621+
curses_setupterm_set_called();
35273622
Py_RETURN_NONE;
35283623
}
35293624

@@ -4332,7 +4427,7 @@ _curses_start_color_impl(PyObject *module)
43324427
return NULL;
43334428
}
43344429

4335-
curses_start_color_called = TRUE;
4430+
curses_start_color_set_called();
43364431

43374432
PyObject *module_dict = PyModule_GetDict(module); // borrowed
43384433
if (module_dict == NULL) {
@@ -4854,21 +4949,24 @@ static PyMethodDef PyCurses_methods[] = {
48544949
initialised or not. */
48554950

48564951
static inline int
4857-
curses_capi_setupterm_called(void)
4952+
curses_capi_setupterm_was_called(void)
48584953
{
4859-
return _PyCursesCheckFunction(curses_setupterm_called, "setupterm");
4954+
int called = curses_setupterm_was_called();
4955+
return _PyCursesStatelessCheckWasCalled(called, "setupterm");
48604956
}
48614957

48624958
static inline int
4863-
curses_capi_initscr_called(void)
4959+
curses_capi_initscr_was_called(void)
48644960
{
4865-
return _PyCursesCheckFunction(curses_initscr_called, "initscr");
4961+
int called = curses_initscr_was_called();
4962+
return _PyCursesStatelessCheckWasCalled(called, "initscr");
48664963
}
48674964

48684965
static inline int
4869-
curses_capi_start_color_called(void)
4966+
curses_capi_start_color_was_called(void)
48704967
{
4871-
return _PyCursesCheckFunction(curses_start_color_called, "start_color");
4968+
int called = curses_start_color_was_called();
4969+
return _PyCursesStatelessCheckWasCalled(called, "start_color");
48724970
}
48734971

48744972
static void *
@@ -4881,9 +4979,9 @@ curses_capi_new(_cursesmodule_state *state)
48814979
return NULL;
48824980
}
48834981
capi[0] = (void *)Py_NewRef(state->window_type);
4884-
capi[1] = curses_capi_setupterm_called;
4885-
capi[2] = curses_capi_initscr_called;
4886-
capi[3] = curses_capi_start_color_called;
4982+
capi[1] = curses_capi_setupterm_was_called;
4983+
capi[2] = curses_capi_initscr_was_called;
4984+
capi[3] = curses_capi_start_color_was_called;
48874985
return (void *)capi;
48884986
}
48894987

@@ -4944,9 +5042,24 @@ curses_capi_capsule_new(void *capi)
49445042

49455043
/* Module initialization */
49465044

5045+
/* Indicate whether the module has been loaded or not. */
5046+
static int curses_module_loaded = 0;
5047+
49475048
static int
49485049
cursesmodule_exec(PyObject *module)
49495050
{
5051+
if (_Py_atomic_load_int(&curses_module_loaded)) {
5052+
PyErr_SetString(PyExc_ImportError,
5053+
"module 'curses' can only be loaded once per process");
5054+
return -1;
5055+
}
5056+
5057+
#ifdef Py_GIL_DISABLED
5058+
_Py_atomic_store_int(&curses_module_loaded, 1);
5059+
#else
5060+
curses_module_loaded = 1;
5061+
#endif
5062+
49505063
_cursesmodule_state *state = get_cursesmodule_state(module);
49515064
/* Initialize object type */
49525065
state->window_type = (PyTypeObject *)PyType_FromModuleAndSpec(

0 commit comments

Comments
 (0)
0