3939
4040#include "docstrings.h"
4141
42+ struct PyDecContextObject ;
43+
4244typedef struct {
4345 PyTypeObject * PyDecContextManager_Type ;
4446 PyTypeObject * PyDecContext_Type ;
@@ -50,6 +52,15 @@ typedef struct {
5052 /* Top level Exception; inherits from ArithmeticError */
5153 PyObject * DecimalException ;
5254
55+ #ifndef WITH_DECIMAL_CONTEXTVAR
56+ /* Key for thread state dictionary */
57+ PyObject * tls_context_key ;
58+ /* Invariant: NULL or the most recently accessed thread local context */
59+ struct PyDecContextObject * cached_context ;
60+ #else
61+ PyObject * current_context_var ;
62+ #endif
63+
5364 /* Template for creating new thread contexts, calling Context() without
5465 * arguments and initializing the module_context on first access. */
5566 PyObject * default_context_template ;
@@ -104,7 +115,7 @@ typedef struct {
104115 uint32_t * flags ;
105116} PyDecSignalDictObject ;
106117
107- typedef struct {
118+ typedef struct PyDecContextObject {
108119 PyObject_HEAD
109120 mpd_context_t ctx ;
110121 PyObject * traps ;
@@ -119,7 +130,6 @@ typedef struct {
119130 PyObject * global ;
120131} PyDecContextManagerObject ;
121132
122-
123133#undef MPD
124134#undef CTX
125135#define PyDec_CheckExact (st , v ) Py_IS_TYPE(v, (st)->PyDec_Type)
@@ -145,16 +155,6 @@ incr_false(void)
145155 return Py_NewRef (Py_False );
146156}
147157
148-
149- #ifndef WITH_DECIMAL_CONTEXTVAR
150- /* Key for thread state dictionary */
151- static PyObject * tls_context_key = NULL ;
152- /* Invariant: NULL or the most recently accessed thread local context */
153- static PyDecContextObject * cached_context = NULL ;
154- #else
155- static PyObject * current_context_var = NULL ;
156- #endif
157-
158158/* Error codes for functions that return signals or conditions */
159159#define DEC_INVALID_SIGNALS (MPD_Max_status+1U)
160160#define DEC_ERR_OCCURRED (DEC_INVALID_SIGNALS<<1)
@@ -1565,7 +1565,8 @@ current_context_from_dict(void)
15651565 return NULL ;
15661566 }
15671567
1568- PyObject * tl_context = PyDict_GetItemWithError (dict , tls_context_key );
1568+ PyObject * tl_context ;
1569+ tl_context = PyDict_GetItemWithError (dict , modstate -> tls_context_key );
15691570 if (tl_context != NULL ) {
15701571 /* We already have a thread local context. */
15711572 CONTEXT_CHECK (modstate , tl_context );
@@ -1576,13 +1577,13 @@ current_context_from_dict(void)
15761577 }
15771578
15781579 /* Set up a new thread local context. */
1579- tl_context = context_copy (state -> default_context_template , NULL );
1580+ tl_context = context_copy (modstate -> default_context_template , NULL );
15801581 if (tl_context == NULL ) {
15811582 return NULL ;
15821583 }
15831584 CTX (tl_context )-> status = 0 ;
15841585
1585- if (PyDict_SetItem (dict , tls_context_key , tl_context ) < 0 ) {
1586+ if (PyDict_SetItem (dict , modstate -> tls_context_key , tl_context ) < 0 ) {
15861587 Py_DECREF (tl_context );
15871588 return NULL ;
15881589 }
@@ -1591,8 +1592,8 @@ current_context_from_dict(void)
15911592
15921593 /* Cache the context of the current thread, assuming that it
15931594 * will be accessed several times before a thread switch. */
1594- cached_context = (PyDecContextObject * )tl_context ;
1595- cached_context -> tstate = tstate ;
1595+ modstate -> cached_context = (PyDecContextObject * )tl_context ;
1596+ modstate -> cached_context -> tstate = tstate ;
15961597
15971598 /* Borrowed reference with refcount==1 */
15981599 return tl_context ;
@@ -1603,8 +1604,9 @@ static PyObject *
16031604current_context (void )
16041605{
16051606 PyThreadState * tstate = _PyThreadState_GET ();
1606- if (cached_context && cached_context -> tstate == tstate ) {
1607- return (PyObject * )cached_context ;
1607+ decimal_state * modstate = GLOBAL_STATE ();
1608+ if (modstate -> cached_context && modstate -> cached_context -> tstate == tstate ) {
1609+ return (PyObject * )(modstate -> cached_context );
16081610 }
16091611
16101612 return current_context_from_dict ();
@@ -1662,8 +1664,8 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
16621664 Py_INCREF (v );
16631665 }
16641666
1665- cached_context = NULL ;
1666- if (PyDict_SetItem (dict , tls_context_key , v ) < 0 ) {
1667+ state -> cached_context = NULL ;
1668+ if (PyDict_SetItem (dict , state -> tls_context_key , v ) < 0 ) {
16671669 Py_DECREF (v );
16681670 return NULL ;
16691671 }
@@ -1682,7 +1684,7 @@ init_current_context(void)
16821684 }
16831685 CTX (tl_context )-> status = 0 ;
16841686
1685- PyObject * tok = PyContextVar_Set (current_context_var , tl_context );
1687+ PyObject * tok = PyContextVar_Set (state -> current_context_var , tl_context );
16861688 if (tok == NULL ) {
16871689 Py_DECREF (tl_context );
16881690 return NULL ;
@@ -1696,7 +1698,8 @@ static inline PyObject *
16961698current_context (void )
16971699{
16981700 PyObject * tl_context ;
1699- if (PyContextVar_Get (current_context_var , NULL , & tl_context ) < 0 ) {
1701+ decimal_state * state = GLOBAL_STATE ();
1702+ if (PyContextVar_Get (state -> current_context_var , NULL , & tl_context ) < 0 ) {
17001703 return NULL ;
17011704 }
17021705
@@ -1744,7 +1747,7 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
17441747 Py_INCREF (v );
17451748 }
17461749
1747- PyObject * tok = PyContextVar_Set (current_context_var , v );
1750+ PyObject * tok = PyContextVar_Set (state -> current_context_var , v );
17481751 Py_DECREF (v );
17491752 if (tok == NULL ) {
17501753 return NULL ;
@@ -5987,10 +5990,11 @@ PyInit__decimal(void)
59875990 Py_NewRef (state -> default_context_template )));
59885991
59895992#ifndef WITH_DECIMAL_CONTEXTVAR
5990- ASSIGN_PTR (tls_context_key , PyUnicode_FromString ("___DECIMAL_CTX__" ));
5993+ ASSIGN_PTR (state -> tls_context_key ,
5994+ PyUnicode_FromString ("___DECIMAL_CTX__" ));
59915995 CHECK_INT (PyModule_AddObject (m , "HAVE_CONTEXTVAR" , Py_NewRef (Py_False )));
59925996#else
5993- ASSIGN_PTR (current_context_var , PyContextVar_New ("decimal_context" , NULL ));
5997+ ASSIGN_PTR (state -> current_context_var , PyContextVar_New ("decimal_context" , NULL ));
59945998 CHECK_INT (PyModule_AddObject (m , "HAVE_CONTEXTVAR" , Py_NewRef (Py_True )));
59955999#endif
59966000 CHECK_INT (PyModule_AddObject (m , "HAVE_THREADS" , Py_NewRef (Py_True )));
@@ -6049,9 +6053,9 @@ PyInit__decimal(void)
60496053 Py_CLEAR (state -> DecimalTuple ); /* GCOV_NOT_REACHED */
60506054 Py_CLEAR (state -> default_context_template ); /* GCOV_NOT_REACHED */
60516055#ifndef WITH_DECIMAL_CONTEXTVAR
6052- Py_CLEAR (tls_context_key ); /* GCOV_NOT_REACHED */
6056+ Py_CLEAR (state -> tls_context_key ); /* GCOV_NOT_REACHED */
60536057#else
6054- Py_CLEAR (current_context_var ); /* GCOV_NOT_REACHED */
6058+ Py_CLEAR (state -> current_context_var ); /* GCOV_NOT_REACHED */
60556059#endif
60566060 Py_CLEAR (state -> basic_context_template ); /* GCOV_NOT_REACHED */
60576061 Py_CLEAR (state -> extended_context_template ); /* GCOV_NOT_REACHED */
0 commit comments