2222// src: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
2323#define SLEEF_QUAD_DECIMAL_DIG 36
2424
25+ #if PY_VERSION_HEX < 0x30d00b3
26+ static PyThread_type_lock sleef_lock ;
27+ #define LOCK_SLEEF PyThread_acquire_lock(sleef_lock, WAIT_LOCK)
28+ #define UNLOCK_SLEEF PyThread_release_lock(sleef_lock)
29+ #else
30+ static PyMutex sleef_lock = {0 };
31+ #define LOCK_SLEEF PyMutex_Lock(&sleef_lock)
32+ #define UNLOCK_SLEEF PyMutex_Unlock(&sleef_lock)
33+ #endif
34+
35+
36+
2537
2638QuadPrecisionObject *
2739QuadPrecision_raw_new (QuadBackendType backend )
@@ -422,13 +434,16 @@ QuadPrecision_is_integer(QuadPrecisionObject *self, PyObject *Py_UNUSED(ignored)
422434 }
423435}
424436
425- // this is thread-unsafe
426437PyObject * quad_to_pylong (Sleef_quad value )
427438{
428439 char buffer [128 ];
440+
441+ // Sleef_snprintf call is thread-unsafe
442+ // LOCK_SLEEF;
429443 // Format as integer (%.0Qf gives integer with no decimal places)
430444 // Q modifier means pass Sleef_quad by value
431445 int written = Sleef_snprintf (buffer , sizeof (buffer ), "%.0Qf" , value );
446+ // UNLOCK_SLEEF;
432447 if (written < 0 || written >= sizeof (buffer )) {
433448 PyErr_SetString (PyExc_RuntimeError , "Failed to convert quad to string" );
434449 return NULL ;
@@ -503,7 +518,6 @@ QuadPrecision_as_integer_ratio(QuadPrecisionObject *self, PyObject *Py_UNUSED(ig
503518 exponent -- ;
504519 }
505520
506-
507521 // numerator and denominators can't fit in int
508522 // convert items to PyLongObject from string instead
509523
@@ -587,6 +601,13 @@ PyTypeObject QuadPrecision_Type = {
587601int
588602init_quadprecision_scalar (void )
589603{
604+ #if PY_VERSION_HEX < 0x30d00b3
605+ sleef_lock = PyThread_allocate_lock ();
606+ if (sleef_lock == NULL ) {
607+ PyErr_NoMemory ();
608+ return -1 ;
609+ }
610+ #endif
590611 QuadPrecision_Type .tp_base = & PyFloatingArrType_Type ;
591612 return PyType_Ready (& QuadPrecision_Type );
592613}
0 commit comments