Download venv/lib/python3.10/site-packages/Cython/Utility/ModuleSetupCode.c from Matt300209/eval_venv: direct link, hf CLI and curl.
- Browser
- Download file 112 kB
-
https://huggingface.co/Matt300209/eval_venv/resolve/main/venv/lib/python3.10/site-packages/Cython/Utility/ModuleSetupCode.c
- Command line
-
hf download hf://Matt300209/eval_venv/venv/lib/python3.10/site-packages/Cython/Utility/ModuleSetupCode.c
-
curl -L -o ModuleSetupCode.c https://huggingface.co/Matt300209/eval_venv/resolve/main/venv/lib/python3.10/site-packages/Cython/Utility/ModuleSetupCode.c
112 kB
| /////////////// InitLimitedAPI /////////////// | |
| // Use Py_LIMITED_API as the main control for Cython's limited API mode. | |
| // However it's still possible to define CYTHON_LIMITED_API alone to | |
| // force Cython to use Limited-API code without enforcing it in Python. | |
| /////////////// CModulePreamble /////////////// | |
| // For use in DL_IMPORT/DL_EXPORT macros. | |
| // CPython has required PY_LONG_LONG support for years, even if HAVE_LONG_LONG is not defined for us | |
| // For the limited API it often makes sense to use Py_LIMITED_API rather than PY_VERSION_HEX | |
| // when doing version checks. | |
| /* For very preliminary testing purposes. Most variables are set the same as PyPy. | |
| The existence of this section does not imply that anything works or is even tested */ | |
| // GRAALVM_PYTHON test comes before PyPy test because GraalPython unhelpfully defines PYPY_VERSION | |
| // EXPERIMENTAL !! | |
| // CYTHON_CLINE_IN_TRACEBACK is currently disabled for the Limited API | |
| // PyObject_CallFinalizerFromDealloc is missing and not easily replaced | |
| // Before Py3.10, PyObject_GetSlot() rejects static (non-heap) types. | |
| // Use thread-safe CPython C API calls to manipulate list contents | |
| // Python 3.11a2 hid _PyLong_FormatAdvancedWriter and _PyFloat_FormatAdvancedWriter | |
| // therefore disable unicode writer until a better alternative appears | |
| // CYTHON_AVOID_BORROWED_REFS - Avoid borrowed references and always request owned references directly instead. | |
| // CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS - Avoid borrowed references that are not thread-safe in the free-threaded build of CPython. | |
| // CYTHON_ASSUME_SAFE_MACROS - Assume that macro calls do not fail and do not raise exceptions. | |
| // CYTHON_ASSUME_SAFE_SIZE - Assume that Py*_GET_SIZE() calls do not fail and do not raise exceptions. | |
| // FIXME: FastGIL can probably be supported also in CPython 3.12 but needs to be adapted. | |
| // The gain is unclear, however, since the GIL handling itself became faster in recent CPython versions. | |
| // CPython 3.6 introduced METH_FASTCALL but with slightly different | |
| // semantics. It became stable starting from CPython 3.7. | |
| // CYTHON_USE_MODULE_STATE - Use a module state/globals struct tied to the module object. | |
| // EXPERIMENTAL !! | |
| // Python 3.12a5 deprecated "ma_version_tag" | |
| // and we use static variables with dict versions so it's incompatible with module state | |
| // Possibly needs a bit of clearing up, however: | |
| // the limited API doesn't define CYTHON_FAST_PYCCALL (because that involves | |
| // a lot of access to internals) but does define CYTHON_VECTORCALL because | |
| // that's available cleanly from Python 3.12. Note that only VectorcallDict isn't | |
| // available though. | |
| /* Whether to use METH_FASTCALL with a fake backported implementation of vectorcall */ | |
| /* These short defines from the PyLong header can easily conflict with other code */ | |
| /* Compile-time sanity check that these are indeed equal. Github issue #2670. */ | |
| enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; | |
| // restrict | |
| // unused attribute | |
| /* for clang __has_cpp_attribute(maybe_unused) is true even before C++17 | |
| * but leads to warnings with -pedantic, since it is a C++17 feature */ | |
| template<class T> void CYTHON_UNUSED_VAR( const T& ) { } | |
| // msvc doesn't set __cplusplus to a useful value | |
| typedef unsigned char uint8_t; | |
| typedef unsigned short uint16_t; | |
| typedef unsigned int uint32_t; | |
| typedef unsigned __int8 uint8_t; | |
| typedef unsigned __int16 uint16_t; | |
| typedef unsigned __int32 uint32_t; | |
| typedef unsigned long long __pyx_uintptr_t; | |
| typedef unsigned int __pyx_uintptr_t; | |
| typedef unsigned __int64 __pyx_uintptr_t; | |
| typedef unsigned __int32 __pyx_uintptr_t; | |
| typedef uintptr_t __pyx_uintptr_t; | |
| /* for clang __has_cpp_attribute(fallthrough) is true even before C++17 | |
| * but leads to warnings with -pedantic, since it is a C++17 feature */ | |
| template <typename T> | |
| struct __PYX_IS_UNSIGNED_IMPL {static const bool value = T(0) < T(-1);}; | |
| // reinterpret | |
| // TODO: refactor existing code to use those macros | |
| // #define __PYX_REINTERPRET_POINTER(pointer_type, pointer) ((pointer_type)(void *)(pointer)) | |
| // #define __PYX_RUNTIME_REINTERPRET(type, var) (*(type *)(&var)) | |
| /////////////// CInitCode /////////////// | |
| // inline attribute | |
| /////////////// CppInitCode /////////////// | |
| // inline attribute | |
| // Work around clang bug https://stackoverflow.com/questions/21847816/c-invoke-nested-template-class-destructor | |
| // (even without the clang bug, the need not to know the typename is generally a benefit) | |
| template<typename T> | |
| void __Pyx_call_destructor(T& x) { | |
| x.~T(); | |
| } | |
| // Used for temporary variables of "reference" type. | |
| template<typename T> | |
| class __Pyx_FakeReference { | |
| public: | |
| __Pyx_FakeReference() : ptr(NULL) { } | |
| // __Pyx_FakeReference(T& ref) : ptr(&ref) { } | |
| // Const version needed as Cython doesn't know about const overloads (e.g. for stl containers). | |
| __Pyx_FakeReference(const T& ref) : ptr(const_cast<T*>(&ref)) { } | |
| T *operator->() { return ptr; } | |
| T *operator&() { return ptr; } | |
| operator T&() { return *ptr; } | |
| // TODO(robertwb): Delegate all operators (or auto-generate unwrapping code where needed). | |
| template<typename U> bool operator ==(const U& other) const { return *ptr == other; } | |
| template<typename U> bool operator !=(const U& other) const { return *ptr != other; } | |
| template<typename U> bool operator==(const __Pyx_FakeReference<U>& other) const { return *ptr == *other.ptr; } | |
| template<typename U> bool operator!=(const __Pyx_FakeReference<U>& other) const { return *ptr != *other.ptr; } | |
| private: | |
| T *ptr; | |
| }; | |
| /////////////// PythonCompatibility /////////////// | |
| //@substitute: naming | |
| // TODO: remove this block | |
| // Cython uses these constants but they are not available in the limited API. | |
| // Therefore define them as static variables and look them up at module init. | |
| static int CO_OPTIMIZED; | |
| static int CO_NEWLOCALS; | |
| static int CO_VARARGS; | |
| static int CO_VARKEYWORDS; | |
| static int CO_ASYNC_GENERATOR; | |
| static int CO_GENERATOR; | |
| static int CO_COROUTINE; | |
| static int __Pyx_init_co_variables(void); /* proto */ | |
| // already defined for Stackless Python (all versions) and C-Python >= 3.7 | |
| // value if defined: Stackless Python < 3.6: 0x80 else 0x100 | |
| // new in CPython 3.6, but changed in 3.7 - see | |
| // positional-only parameters: | |
| // https://bugs.python.org/issue29464 | |
| // const args: | |
| // https://bugs.python.org/issue32240 | |
| typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); | |
| // new in CPython 3.7, used to be old signature of _PyCFunctionFast() in 3.6 | |
| typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, | |
| Py_ssize_t nargs, PyObject *kwnames); | |
| typedef PyObject *(*__pyx_vectorcallfunc)(PyObject *callable, PyObject *const *args, | |
| size_t nargsf, PyObject *kwnames); | |
| // These PyCFunction related macros get redefined in CythonFunction.c. | |
| // We need our own copies because the inline functions in CPython have a type-check assert | |
| // that breaks with a CyFunction in debug mode. | |
| // It's probably easier for non-CPythons to support PyCFunction_GET_FUNCTION() than the object struct layout. | |
| // Unused in CYTHON_COMPILING_IN_LIMITED_API. | |
| static CYTHON_INLINE PyObject* __Pyx_CyOrPyCFunction_GET_SELF(PyObject *func) { | |
| return (__Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_STATIC) ? NULL : ((PyCFunctionObject*)func)->m_self; | |
| } | |
| // Only used if CYTHON_COMPILING_IN_CPYTHON. | |
| static CYTHON_INLINE int __Pyx__IsSameCFunction(PyObject *func, void (*cfunc)(void)) { | |
| return PyCFunction_Check(func) && PyCFunction_GetFunction(func) == (PyCFunction) cfunc; | |
| return PyCFunction_Check(func) && PyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; | |
| } | |
| // PEP-573: PyCFunction holds reference to defining class (PyCMethodObject) | |
| typedef PyObject *(*__Pyx_PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *); | |
| // __Pyx_PyCode_HasFreeVars isn't easily emulated in the limited API (but isn't really necessary) | |
| static CYTHON_INLINE void *__Pyx__PyModule_GetState(PyObject *op) | |
| { | |
| void *result; | |
| result = PyModule_GetState(op); | |
| if (!result) | |
| Py_FatalError("Couldn't find the module state"); | |
| return result; | |
| } | |
| // Define a macro with a cast because the modulestate type isn't known yet and | |
| // is a typedef struct so impossible to forward declare | |
| // The "Try" variants may return NULL on static types with the Limited API on earlier versions | |
| // so should be used for optimization rather than where a result is required. | |
| // _PyDict_GetItem_KnownHash() existed from CPython 3.5 to 3.12, but it was | |
| // dropping exceptions in 3.5. Since 3.6, exceptions are kept. | |
| static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStr(PyObject *dict, PyObject *name) { | |
| PyObject *res = __Pyx_PyDict_GetItemStrWithError(dict, name); | |
| if (res == NULL) PyErr_Clear(); | |
| return res; | |
| } | |
| static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, PyObject *name) { | |
| // This is tricky - we should return a borrowed reference but not swallow non-KeyError exceptions. 8-| | |
| // But: this function is only used in Py2 and older PyPys, | |
| // and currently only for argument parsing and other non-correctness-critical lookups | |
| // and we know that 'name' is an interned 'str' with pre-calculated hash value (only comparisons can fail), | |
| // thus, performance matters more than correctness here, especially in the "not found" case. | |
| // So we ignore any exceptions in old PyPys ... | |
| return PyDict_GetItem(dict, name); | |
| // and hack together a stripped-down and modified PyDict_GetItem() in CPython 2. | |
| PyDictEntry *ep; | |
| PyDictObject *mp = (PyDictObject*) dict; | |
| long hash = ((PyStringObject *) name)->ob_shash; | |
| assert(hash != -1); /* hash values of interned strings are always initialised */ | |
| ep = (mp->ma_lookup)(mp, name, hash); | |
| if (ep == NULL) { | |
| // error occurred | |
| return NULL; | |
| } | |
| // found or not found | |
| return ep->me_value; | |
| } | |
| /* Type slots */ | |
| // There is no replacement for "Py_TYPE(obj)->iternext" in the C-API. | |
| // PyIter_Next() discards the StopIteration, unlike Python's "next()". | |
| // In Py3.8+, instances of heap types need to decref their type on deallocation. | |
| // https://bugs.python.org/issue35810 | |
| // __Pyx_PyUnicode_DATA() and __Pyx_PyUnicode_READ() must go together, e.g. for iteration. | |
| //#define __Pyx_PyUnicode_WRITE(k, d, i, ch) /* not available */ | |
| // Py3.12 / PEP-623 removed wstr type unicode strings and all of the PyUnicode_READY() machinery. | |
| // Avoid calling deprecated C-API functions in Py3.9+ that PEP-623 schedules for removal in Py3.12. | |
| // https://www.python.org/dev/peps/pep-0623/ | |
| // ("..." % x) must call PyNumber_Remainder() if x is a string subclass that implements "__rmod__()". | |
| static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) { | |
| *result = PyObject_GetItem(dict, key); | |
| if (*result == NULL) { | |
| if (PyErr_ExceptionMatches(PyExc_KeyError)) { | |
| PyErr_Clear(); | |
| return 0; | |
| } | |
| return -1; | |
| } | |
| return 1; | |
| } | |
| static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) { | |
| *result = PyDict_GetItemWithError(dict, key); | |
| if (*result == NULL) { | |
| return PyErr_Occurred() ? -1 : 0; | |
| } | |
| Py_INCREF(*result); | |
| return 1; | |
| } | |
| // No-op macro for calling Py_VISIT() on known constants that can never participate in reference cycles. | |
| // Users can define "CYTHON_DEBUG_VISIT_CONST=1" to help in debugging reference issues. | |
| // NOTE: might fail with exception => check for -1 | |
| // NOTE: this doesn't leak a reference to whatever is at o[i] | |
| // These all need exception checks for -1. | |
| static CYTHON_INLINE PyObject *__Pyx_PyImport_AddModuleRef(const char *name) { | |
| PyObject *module = PyImport_AddModule(name); | |
| Py_XINCREF(module); | |
| return module; | |
| } | |
| // backport of PyAsyncMethods from Py3.10 to older Py3.x versions | |
| typedef enum { | |
| PYGEN_RETURN = 0, | |
| PYGEN_ERROR = -1, | |
| PYGEN_NEXT = 1, | |
| } __Pyx_PySendResult; | |
| typedef __Pyx_PySendResult (*__Pyx_pyiter_sendfunc)(PyObject *iter, PyObject *value, PyObject **result); | |
| // "Py_am_send" requires Py3.10 when using type specs (which utility code types do). | |
| // PyAsyncMethods in Py<3.10 lacks "am_send" | |
| typedef struct { | |
| unaryfunc am_await; | |
| unaryfunc am_aiter; | |
| unaryfunc am_anext; | |
| __Pyx_pyiter_sendfunc am_send; | |
| } __Pyx_PyAsyncMethodsStruct; | |
| // Use a flag in Py < 3.10 to mark coroutines that have the "am_send" field. | |
| // PyMem_Calloc *is* in the Stable ABI in all the Limited API versions we care about. | |
| // However, it is omitted from the Python headers which means that C incorrectly | |
| // assumes it returns an int (and generates dubious code on based on that assumption). | |
| // Therefore, copy the prototype. | |
| extern "C" | |
| PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize); /* proto */ | |
| // returns 1 for success and 0 for failure to enable it to be chained in an && | |
| static int __Pyx_init_co_variable(PyObject *inspect, const char* name, int *write_to) { | |
| int value; | |
| PyObject *py_value = PyObject_GetAttrString(inspect, name); | |
| if (!py_value) return 0; | |
| // There's a small chance of overflow here, but it'd only happen if inspect was set up wrongly. | |
| value = (int) PyLong_AsLong(py_value); | |
| Py_DECREF(py_value); | |
| *write_to = value; | |
| return value != -1 || !PyErr_Occurred(); | |
| } | |
| // Returns 0 on success and -1 on failure for normal error handling | |
| static int __Pyx_init_co_variables(void) { | |
| PyObject *inspect; | |
| int result; | |
| inspect = PyImport_ImportModule("inspect"); | |
| result = | |
| __Pyx_init_co_variable(inspect, "CO_OPTIMIZED", &CO_OPTIMIZED) && | |
| __Pyx_init_co_variable(inspect, "CO_NEWLOCALS", &CO_NEWLOCALS) && | |
| __Pyx_init_co_variable(inspect, "CO_VARARGS", &CO_VARARGS) && | |
| __Pyx_init_co_variable(inspect, "CO_VARKEYWORDS", &CO_VARKEYWORDS) && | |
| __Pyx_init_co_variable(inspect, "CO_ASYNC_GENERATOR", &CO_ASYNC_GENERATOR) && | |
| __Pyx_init_co_variable(inspect, "CO_GENERATOR", &CO_GENERATOR) && | |
| __Pyx_init_co_variable(inspect, "CO_COROUTINE", &CO_COROUTINE) && | |
| 1; | |
| Py_DECREF(inspect); | |
| return result ? 0 : -1; | |
| } | |
| static int __Pyx_init_co_variables(void) { | |
| return 0; // It's a limited API-only feature | |
| } | |
| /////////////// CythonABIVersion.proto /////////////// | |
| //@proto_block: module_declarations | |
| // This needs to go after the utility code 'proto' section but before user code and utility impl. | |
| // The limited API makes some significant changes to data structures, so we don't | |
| // want to share the implementations compiled with and without the limited API. | |
| // affects destruction of async generator/coroutines | |
| // affects allocation/deallocation of async generator objects. | |
| /////////////// PythonCompatibility.init /////////////// | |
| if (likely(__Pyx_init_co_variables() == 0)); else | |
| /////////////// IncludeStructmemberH.proto /////////////// | |
| //@proto_block: utility_code_proto_before_types | |
| /////////////// SmallCodeConfig /////////////// | |
| /////////////// PyModInitFuncType /////////////// | |
| // define this to PyObject * manually because PyMODINIT_FUNC adds __declspec(dllexport) to it's definition. | |
| /////////////// FastTypeChecks.proto /////////////// | |
| static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b);/*proto*/ | |
| static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b);/*proto*/ | |
| static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type);/*proto*/ | |
| static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2);/*proto*/ | |
| static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2) { | |
| return PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2); | |
| } | |
| /////////////// FastTypeChecks /////////////// | |
| //@requires: Exceptions.c::PyThreadStateGet | |
| //@requires: Exceptions.c::PyErrFetchRestore | |
| static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { | |
| while (a) { | |
| a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*); | |
| if (a == b) | |
| return 1; | |
| } | |
| return b == &PyBaseObject_Type; | |
| } | |
| static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { | |
| PyObject *mro; | |
| if (a == b) return 1; | |
| mro = a->tp_mro; | |
| if (likely(mro)) { | |
| Py_ssize_t i, n; | |
| n = PyTuple_GET_SIZE(mro); | |
| for (i = 0; i < n; i++) { | |
| if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| // should only get here for incompletely initialised types, i.e. never under normal usage patterns | |
| return __Pyx_InBases(a, b); | |
| } | |
| static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b) { | |
| PyObject *mro; | |
| if (cls == a || cls == b) return 1; | |
| mro = cls->tp_mro; | |
| if (likely(mro)) { | |
| Py_ssize_t i, n; | |
| n = PyTuple_GET_SIZE(mro); | |
| for (i = 0; i < n; i++) { | |
| PyObject *base = PyTuple_GET_ITEM(mro, i); | |
| if (base == (PyObject *)a || base == (PyObject *)b) | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| // should only get here for incompletely initialised types, i.e. never under normal usage patterns | |
| return __Pyx_InBases(cls, a) || __Pyx_InBases(cls, b); | |
| } | |
| static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { | |
| if (exc_type1) { | |
| return __Pyx_IsAnySubtype2((PyTypeObject*)err, (PyTypeObject*)exc_type1, (PyTypeObject*)exc_type2); | |
| } else { | |
| return __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); | |
| } | |
| } | |
| // so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument | |
| // => optimise for that case | |
| static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { | |
| Py_ssize_t i, n; | |
| assert(PyExceptionClass_Check(exc_type)); | |
| n = PyTuple_GET_SIZE(tuple); | |
| // the tight subtype checking in Py3 allows faster out-of-order comparison | |
| for (i=0; i<n; i++) { | |
| if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1; | |
| } | |
| for (i=0; i<n; i++) { | |
| PyObject *t = PyTuple_GET_ITEM(tuple, i); | |
| if (likely(PyExceptionClass_Check(t))) { | |
| if (__Pyx_inner_PyErr_GivenExceptionMatches2(exc_type, NULL, t)) return 1; | |
| } else { | |
| // FIXME: Py3: PyErr_SetString(PyExc_TypeError, "catching classes that do not inherit from BaseException is not allowed"); | |
| } | |
| } | |
| return 0; | |
| } | |
| static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) { | |
| if (likely(err == exc_type)) return 1; | |
| if (likely(PyExceptionClass_Check(err))) { | |
| if (likely(PyExceptionClass_Check(exc_type))) { | |
| return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type); | |
| } else if (likely(PyTuple_Check(exc_type))) { | |
| return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type); | |
| } else { | |
| // FIXME: Py3: PyErr_SetString(PyExc_TypeError, "catching classes that do not inherit from BaseException is not allowed"); | |
| } | |
| } | |
| return PyErr_GivenExceptionMatches(err, exc_type); | |
| } | |
| static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) { | |
| // Only used internally with known exception types => pure safety check assertions. | |
| assert(PyExceptionClass_Check(exc_type1)); | |
| assert(PyExceptionClass_Check(exc_type2)); | |
| if (likely(err == exc_type1 || err == exc_type2)) return 1; | |
| if (likely(PyExceptionClass_Check(err))) { | |
| return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2); | |
| } | |
| return (PyErr_GivenExceptionMatches(err, exc_type1) || PyErr_GivenExceptionMatches(err, exc_type2)); | |
| } | |
| /////////////// MathInitCode /////////////// | |
| static CYTHON_INLINE float __PYX_NAN() { | |
| // Initialize NaN. The sign is irrelevant, an exponent with all bits 1 and | |
| // a nonzero mantissa means NaN. If the first bit in the mantissa is 1, it is | |
| // a quiet NaN. | |
| float value; | |
| memset(&value, 0xFF, sizeof(value)); | |
| return value; | |
| } | |
| /////////////// ForceInitThreads.proto /////////////// | |
| //@proto_block: utility_code_proto_before_types | |
| /////////////// ModuleCreationPEP489 /////////////// | |
| //@substitute: naming | |
| // Probably won't work before 3.8, but we don't use restricted API to find that out. | |
| static PY_INT64_T __Pyx_GetCurrentInterpreterId(void) { | |
| { | |
| PyObject *module = PyImport_ImportModule("_interpreters"); // 3.13+ I think | |
| if (!module) { | |
| PyErr_Clear(); // just try the 3.8-3.12 version | |
| module = PyImport_ImportModule("_xxsubinterpreters"); | |
| if (!module) goto bad; | |
| } | |
| PyObject *current = PyObject_CallMethod(module, "get_current", NULL); | |
| Py_DECREF(module); | |
| if (!current) goto bad; | |
| if (PyTuple_Check(current)) { | |
| // I think 3.13+ returns a tuple of (ID, whence), | |
| // but it's obviously a private module so the API changes a bit. | |
| PyObject *new_current = PySequence_GetItem(current, 0); | |
| Py_DECREF(current); | |
| current = new_current; | |
| if (!new_current) goto bad; | |
| } | |
| long long as_c_int = PyLong_AsLongLong(current); | |
| Py_DECREF(current); | |
| return as_c_int; | |
| } | |
| bad: | |
| PySys_WriteStderr("__Pyx_GetCurrentInterpreterId failed. Try setting the C define CYTHON_PEP489_MULTI_PHASE_INIT=0\n"); | |
| return -1; | |
| } | |
| //#if CYTHON_PEP489_MULTI_PHASE_INIT | |
| static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { | |
| static PY_INT64_T main_interpreter_id = -1; | |
| PY_INT64_T current_id = PyInterpreterState_GetIDFromThreadState(PyThreadState_Get()); | |
| PY_INT64_T current_id = PyInterpreterState_GetID(PyInterpreterState_Get()); | |
| PY_INT64_T current_id = __Pyx_GetCurrentInterpreterId(); | |
| PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); | |
| if (unlikely(current_id == -1)) { | |
| return -1; | |
| } | |
| if (main_interpreter_id == -1) { | |
| main_interpreter_id = current_id; | |
| return 0; | |
| } else if (unlikely(main_interpreter_id != current_id)) { | |
| PyErr_SetString( | |
| PyExc_ImportError, | |
| "Interpreter change detected - this module can only be loaded into one interpreter per process."); | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) | |
| { | |
| PyObject *value = PyObject_GetAttrString(spec, from_name); | |
| int result = 0; | |
| if (likely(value)) { | |
| if (allow_none || value != Py_None) { | |
| result = PyDict_SetItemString(moddict, to_name, value); | |
| } | |
| Py_DECREF(value); | |
| } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { | |
| PyErr_Clear(); | |
| } else { | |
| result = -1; | |
| } | |
| return result; | |
| } | |
| static CYTHON_SMALL_CODE PyObject* ${pymodule_create_func_cname}(PyObject *spec, PyModuleDef *def) { | |
| PyObject *module = NULL, *moddict, *modname; | |
| CYTHON_UNUSED_VAR(def); | |
| // For now, we only have exactly one module instance. | |
| if (__Pyx_check_single_interpreter()) | |
| return NULL; | |
| if (${module_cname}) | |
| return __Pyx_NewRef(${module_cname}); | |
| modname = PyObject_GetAttrString(spec, "name"); | |
| if (unlikely(!modname)) goto bad; | |
| module = PyModule_NewObject(modname); | |
| Py_DECREF(modname); | |
| if (unlikely(!module)) goto bad; | |
| moddict = PyModule_GetDict(module); | |
| if (unlikely(!moddict)) goto bad; | |
| // moddict is a borrowed reference | |
| if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; | |
| if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; | |
| if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; | |
| if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; | |
| return module; | |
| bad: | |
| Py_XDECREF(module); | |
| return NULL; | |
| } | |
| //#endif | |
| /////////////// CodeObjectCache.proto /////////////// | |
| //@requires: Synchronization.c::Atomics | |
| typedef PyObject __Pyx_CachedCodeObjectType; | |
| typedef PyCodeObject __Pyx_CachedCodeObjectType; | |
| typedef struct { | |
| __Pyx_CachedCodeObjectType* code_object; | |
| int code_line; | |
| } __Pyx_CodeObjectCacheEntry; | |
| struct __Pyx_CodeObjectCache { | |
| int count; | |
| int max_count; | |
| __Pyx_CodeObjectCacheEntry* entries; | |
| // 0 for none, +ve for readers, -ve for writers. | |
| // | |
| __pyx_atomic_int_type accessor_count; | |
| }; | |
| static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); | |
| static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line); | |
| static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object); | |
| /////////////// CodeObjectCache.module_state_decls //////////////// | |
| struct __Pyx_CodeObjectCache __pyx_code_cache; | |
| /////////////// CodeObjectCache /////////////// | |
| // Note that errors are simply ignored in the code below. | |
| // This is just a cache, if a lookup or insertion fails - so what? | |
| static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { | |
| int start = 0, mid = 0, end = count - 1; | |
| if (end >= 0 && code_line > entries[end].code_line) { | |
| return count; | |
| } | |
| while (start < end) { | |
| mid = start + (end - start) / 2; | |
| if (code_line < entries[mid].code_line) { | |
| end = mid; | |
| } else if (code_line > entries[mid].code_line) { | |
| start = mid + 1; | |
| } else { | |
| return mid; | |
| } | |
| } | |
| if (code_line <= entries[mid].code_line) { | |
| return mid; | |
| } else { | |
| return mid + 1; | |
| } | |
| } | |
| static __Pyx_CachedCodeObjectType *__pyx__find_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line) { | |
| __Pyx_CachedCodeObjectType* code_object; | |
| int pos; | |
| if (unlikely(!code_line) || unlikely(!code_cache->entries)) { | |
| return NULL; | |
| } | |
| pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line); | |
| if (unlikely(pos >= code_cache->count) || unlikely(code_cache->entries[pos].code_line != code_line)) { | |
| return NULL; | |
| } | |
| code_object = code_cache->entries[pos].code_object; | |
| Py_INCREF(code_object); | |
| return code_object; | |
| } | |
| static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line) { | |
| (void)__pyx__find_code_object; | |
| return NULL; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just miss. | |
| struct __Pyx_CodeObjectCache *code_cache = &CGLOBAL(__pyx_code_cache); | |
| __pyx_nonatomic_int_type old_count = __pyx_atomic_incr_acq_rel(&code_cache->accessor_count); | |
| if (old_count < 0) { | |
| // It's being written so currently unreadable. | |
| __pyx_atomic_decr_acq_rel(&code_cache->accessor_count); | |
| return NULL; | |
| } | |
| __Pyx_CachedCodeObjectType *result = __pyx__find_code_object(code_cache, code_line); | |
| __pyx_atomic_decr_acq_rel(&code_cache->accessor_count); | |
| return result; | |
| } | |
| static void __pyx__insert_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line, __Pyx_CachedCodeObjectType* code_object) | |
| { | |
| int pos, i; | |
| __Pyx_CodeObjectCacheEntry* entries = code_cache->entries; | |
| if (unlikely(!code_line)) { | |
| return; | |
| } | |
| if (unlikely(!entries)) { | |
| entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); | |
| if (likely(entries)) { | |
| code_cache->entries = entries; | |
| code_cache->max_count = 64; | |
| code_cache->count = 1; | |
| entries[0].code_line = code_line; | |
| entries[0].code_object = code_object; | |
| Py_INCREF(code_object); | |
| } | |
| return; | |
| } | |
| pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line); | |
| if ((pos < code_cache->count) && unlikely(code_cache->entries[pos].code_line == code_line)) { | |
| __Pyx_CachedCodeObjectType* tmp = entries[pos].code_object; | |
| entries[pos].code_object = code_object; | |
| Py_INCREF(code_object); | |
| Py_DECREF(tmp); | |
| return; | |
| } | |
| if (code_cache->count == code_cache->max_count) { | |
| int new_max = code_cache->max_count + 64; | |
| entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( | |
| code_cache->entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); | |
| if (unlikely(!entries)) { | |
| return; | |
| } | |
| code_cache->entries = entries; | |
| code_cache->max_count = new_max; | |
| } | |
| for (i=code_cache->count; i>pos; i--) { | |
| entries[i] = entries[i-1]; | |
| } | |
| entries[pos].code_line = code_line; | |
| entries[pos].code_object = code_object; | |
| code_cache->count++; | |
| Py_INCREF(code_object); | |
| } | |
| static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object) { | |
| (void)__pyx__insert_code_object; | |
| return; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just fail. | |
| struct __Pyx_CodeObjectCache *code_cache = &CGLOBAL(__pyx_code_cache); | |
| __pyx_nonatomic_int_type expected = 0; | |
| if (!__pyx_atomic_int_cmp_exchange(&code_cache->accessor_count, &expected, INT_MIN)) { | |
| // it's being written or read, Either way we can't do anything | |
| return; | |
| } | |
| __pyx__insert_code_object(code_cache, code_line, code_object); | |
| __pyx_atomic_sub(&code_cache->accessor_count, INT_MIN); | |
| } | |
| /////////////// CodeObjectCache.cleanup /////////////// | |
| { | |
| struct __Pyx_CodeObjectCache *code_cache = &CGLOBAL(__pyx_code_cache); | |
| if (code_cache->entries) { | |
| __Pyx_CodeObjectCacheEntry* entries = code_cache->entries; | |
| int i, count = code_cache->count; | |
| code_cache->count = 0; | |
| code_cache->max_count = 0; | |
| code_cache->entries = NULL; | |
| for (i=0; i<count; i++) { | |
| Py_DECREF(entries[i].code_object); | |
| } | |
| PyMem_Free(entries); | |
| } | |
| } | |
| /////////////// GetRuntimeVersion.proto /////////////// | |
| static unsigned long __Pyx_get_runtime_version(void); | |
| /////////////// GetRuntimeVersion /////////////// | |
| static unsigned long __Pyx_get_runtime_version(void) { | |
| // We will probably never need the alpha/beta status, so avoid the complexity to parse it. | |
| return Py_Version & ~0xFFUL; | |
| static unsigned long __Pyx_cached_runtime_version = 0; | |
| if (__Pyx_cached_runtime_version == 0) { | |
| const char* rt_version = Py_GetVersion(); | |
| unsigned long version = 0; | |
| unsigned long factor = 0x01000000UL; | |
| unsigned int digit = 0; | |
| int i = 0; | |
| while (factor) { | |
| while ('0' <= rt_version[i] && rt_version[i] <= '9') { | |
| digit = digit * 10 + (unsigned int) (rt_version[i] - '0'); | |
| ++i; | |
| } | |
| version += factor * digit; | |
| if (rt_version[i] != '.') | |
| break; | |
| digit = 0; | |
| factor >>= 8; | |
| ++i; | |
| } | |
| __Pyx_cached_runtime_version = version; | |
| } | |
| return __Pyx_cached_runtime_version; | |
| } | |
| /////////////// CheckBinaryVersion.proto /////////////// | |
| static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer); | |
| /////////////// CheckBinaryVersion /////////////// | |
| static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer) { | |
| // runtime version is: -1 => older, 0 => equal, 1 => newer | |
| const unsigned long MAJOR_MINOR = 0xFFFF0000UL; | |
| if ((rt_version & MAJOR_MINOR) == (ct_version & MAJOR_MINOR)) | |
| return 0; | |
| if (likely(allow_newer && (rt_version & MAJOR_MINOR) > (ct_version & MAJOR_MINOR))) | |
| return 1; | |
| { | |
| char message[200]; | |
| PyOS_snprintf(message, sizeof(message), | |
| "compile time Python version %d.%d " | |
| "of module '%.100s' " | |
| "%s " | |
| "runtime version %d.%d", | |
| (int) (ct_version >> 24), (int) ((ct_version >> 16) & 0xFF), | |
| __Pyx_MODULE_NAME, | |
| (allow_newer) ? "was newer than" : "does not match", | |
| (int) (rt_version >> 24), (int) ((rt_version >> 16) & 0xFF) | |
| ); | |
| // returns 0 or -1 | |
| return PyErr_WarnEx(NULL, message, 1); | |
| } | |
| } | |
| /////////////// IsLittleEndian.proto /////////////// | |
| static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); | |
| /////////////// IsLittleEndian /////////////// | |
| static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) | |
| { | |
| union { | |
| uint32_t u32; | |
| uint8_t u8[4]; | |
| } S; | |
| S.u32 = 0x01020304; | |
| return S.u8[0] == 4; | |
| } | |
| /////////////// Refnanny.proto /////////////// | |
| typedef struct { | |
| void (*INCREF)(void*, PyObject*, Py_ssize_t); | |
| void (*DECREF)(void*, PyObject*, Py_ssize_t); | |
| void (*GOTREF)(void*, PyObject*, Py_ssize_t); | |
| void (*GIVEREF)(void*, PyObject*, Py_ssize_t); | |
| void* (*SetupContext)(const char*, Py_ssize_t, const char*); | |
| void (*FinishContext)(void**); | |
| } __Pyx_RefNannyAPIStruct; | |
| static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; | |
| static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/ | |
| /////////////// Refnanny /////////////// | |
| static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { | |
| PyObject *m = NULL, *p = NULL; | |
| void *r = NULL; | |
| m = PyImport_ImportModule(modname); | |
| if (!m) goto end; | |
| p = PyObject_GetAttrString(m, "RefNannyAPI"); | |
| if (!p) goto end; | |
| r = PyLong_AsVoidPtr(p); | |
| end: | |
| Py_XDECREF(p); | |
| Py_XDECREF(m); | |
| return (__Pyx_RefNannyAPIStruct *)r; | |
| } | |
| /////////////// ImportRefnannyAPI /////////////// | |
| __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); | |
| if (!__Pyx_RefNanny) { | |
| PyErr_Clear(); | |
| __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); | |
| if (!__Pyx_RefNanny) | |
| Py_FatalError("failed to import 'refnanny' module"); | |
| } | |
| /////////////// RegisterModuleCleanup.proto /////////////// | |
| //@substitute: naming | |
| static void ${cleanup_cname}(PyObject *self); /*proto*/ | |
| static int __Pyx_RegisterCleanup(void); /*proto*/ | |
| /////////////// RegisterModuleCleanup /////////////// | |
| //@substitute: naming | |
| static PyObject* ${cleanup_cname}_atexit(PyObject *module, PyObject *unused) { | |
| CYTHON_UNUSED_VAR(unused); | |
| ${cleanup_cname}(module); | |
| Py_INCREF(Py_None); return Py_None; | |
| } | |
| static int __Pyx_RegisterCleanup(void) { | |
| // Don't use Py_AtExit because that has a 32-call limit and is called | |
| // after python finalization. | |
| // Also, we try to prepend the cleanup function to "atexit._exithandlers" | |
| // in Py2 because CPython runs them last-to-first. Being run last allows | |
| // user exit code to run before us that may depend on the globals | |
| // and cached objects that we are about to clean up. | |
| static PyMethodDef cleanup_def = { | |
| "__cleanup", (PyCFunction)${cleanup_cname}_atexit, METH_NOARGS, 0}; | |
| PyObject *cleanup_func = 0; | |
| PyObject *atexit = 0; | |
| PyObject *reg = 0; | |
| PyObject *args = 0; | |
| PyObject *res = 0; | |
| int ret = -1; | |
| cleanup_func = PyCFunction_New(&cleanup_def, 0); | |
| if (!cleanup_func) | |
| goto bad; | |
| atexit = PyImport_ImportModule("atexit"); | |
| if (!atexit) | |
| goto bad; | |
| reg = PyObject_GetAttrString(atexit, "_exithandlers"); | |
| if (reg && PyList_Check(reg)) { | |
| PyObject *a, *kw; | |
| a = PyTuple_New(0); | |
| kw = PyDict_New(); | |
| if (!a || !kw) { | |
| Py_XDECREF(a); | |
| Py_XDECREF(kw); | |
| goto bad; | |
| } | |
| args = PyTuple_Pack(3, cleanup_func, a, kw); | |
| Py_DECREF(a); | |
| Py_DECREF(kw); | |
| if (!args) | |
| goto bad; | |
| ret = PyList_Insert(reg, 0, args); | |
| } else { | |
| if (!reg) | |
| PyErr_Clear(); | |
| Py_XDECREF(reg); | |
| reg = PyObject_GetAttrString(atexit, "register"); | |
| if (!reg) | |
| goto bad; | |
| args = PyTuple_Pack(1, cleanup_func); | |
| if (!args) | |
| goto bad; | |
| res = PyObject_CallObject(reg, args); | |
| if (!res) | |
| goto bad; | |
| ret = 0; | |
| } | |
| bad: | |
| Py_XDECREF(cleanup_func); | |
| Py_XDECREF(atexit); | |
| Py_XDECREF(reg); | |
| Py_XDECREF(args); | |
| Py_XDECREF(res); | |
| return ret; | |
| } | |
| /////////////// FastGil.init /////////////// | |
| __Pyx_FastGilFuncInit(); | |
| /////////////// NoFastGil.proto /////////////// | |
| //@proto_block: utility_code_proto_before_types | |
| /////////////// FastGil.proto /////////////// | |
| //@proto_block: utility_code_proto_before_types | |
| struct __Pyx_FastGilVtab { | |
| PyGILState_STATE (*Fast_PyGILState_Ensure)(void); | |
| void (*Fast_PyGILState_Release)(PyGILState_STATE oldstate); | |
| void (*FastGIL_Remember)(void); | |
| void (*FastGIL_Forget)(void); | |
| }; | |
| static void __Pyx_FastGIL_Noop(void) {} | |
| static struct __Pyx_FastGilVtab __Pyx_FastGilFuncs = { | |
| PyGILState_Ensure, | |
| PyGILState_Release, | |
| __Pyx_FastGIL_Noop, | |
| __Pyx_FastGIL_Noop | |
| }; | |
| static void __Pyx_FastGilFuncInit(void); | |
| /////////////// FastGil /////////////// | |
| // The implementations of PyGILState_Ensure/Release calls PyThread_get_key_value | |
| // several times which is turns out to be quite slow (slower in fact than | |
| // acquiring the GIL itself). Simply storing it in a thread local for the | |
| // common case is much faster. | |
| // To make optimal use of this thread local, we attempt to share it between | |
| // modules. | |
| static CYTHON_THREAD_LOCAL PyThreadState *__Pyx_FastGil_tcur = NULL; | |
| static CYTHON_THREAD_LOCAL int __Pyx_FastGil_tcur_depth = 0; | |
| static int __Pyx_FastGil_autoTLSkey = -1; | |
| static CYTHON_INLINE void __Pyx_FastGIL_Remember0(void) { | |
| ++__Pyx_FastGil_tcur_depth; | |
| } | |
| static CYTHON_INLINE void __Pyx_FastGIL_Forget0(void) { | |
| if (--__Pyx_FastGil_tcur_depth == 0) { | |
| __Pyx_FastGil_tcur = NULL; | |
| } | |
| } | |
| static CYTHON_INLINE PyThreadState *__Pyx_FastGil_get_tcur(void) { | |
| PyThreadState *tcur = __Pyx_FastGil_tcur; | |
| if (tcur == NULL) { | |
| tcur = __Pyx_FastGil_tcur = (PyThreadState*)PyThread_get_key_value(__Pyx_FastGil_autoTLSkey); | |
| } | |
| return tcur; | |
| } | |
| static PyGILState_STATE __Pyx_FastGil_PyGILState_Ensure(void) { | |
| int current; | |
| PyThreadState *tcur; | |
| __Pyx_FastGIL_Remember0(); | |
| tcur = __Pyx_FastGil_get_tcur(); | |
| if (tcur == NULL) { | |
| // Uninitialized, need to initialize now. | |
| return PyGILState_Ensure(); | |
| } | |
| current = tcur == __Pyx_PyThreadState_Current; | |
| if (current == 0) { | |
| PyEval_RestoreThread(tcur); | |
| } | |
| ++tcur->gilstate_counter; | |
| return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; | |
| } | |
| static void __Pyx_FastGil_PyGILState_Release(PyGILState_STATE oldstate) { | |
| PyThreadState *tcur = __Pyx_FastGil_get_tcur(); | |
| __Pyx_FastGIL_Forget0(); | |
| if (tcur->gilstate_counter == 1) { | |
| // This is the last lock, do all the cleanup as well. | |
| PyGILState_Release(oldstate); | |
| } else { | |
| --tcur->gilstate_counter; | |
| if (oldstate == PyGILState_UNLOCKED) { | |
| PyEval_SaveThread(); | |
| } | |
| } | |
| } | |
| static void __Pyx_FastGilFuncInit0(void) { | |
| /* Try to detect autoTLSkey. */ | |
| int key; | |
| void* this_thread_state = (void*) PyGILState_GetThisThreadState(); | |
| for (key = 0; key < 100; key++) { | |
| if (PyThread_get_key_value(key) == this_thread_state) { | |
| __Pyx_FastGil_autoTLSkey = key; | |
| break; | |
| } | |
| } | |
| if (__Pyx_FastGil_autoTLSkey != -1) { | |
| PyObject* capsule = NULL; | |
| PyObject* abi_module = NULL; | |
| __Pyx_PyGILState_Ensure = __Pyx_FastGil_PyGILState_Ensure; | |
| __Pyx_PyGILState_Release = __Pyx_FastGil_PyGILState_Release; | |
| __Pyx_FastGIL_Remember = __Pyx_FastGIL_Remember0; | |
| __Pyx_FastGIL_Forget = __Pyx_FastGIL_Forget0; | |
| capsule = PyCapsule_New(&__Pyx_FastGilFuncs, __Pyx_FastGIL_PyCapsule, NULL); | |
| if (capsule) { | |
| abi_module = __Pyx_PyImport_AddModuleRef(__Pyx_FastGIL_ABI_module); | |
| if (abi_module) { | |
| PyObject_SetAttrString(abi_module, __Pyx_FastGIL_PyCapsuleName, capsule); | |
| Py_DECREF(abi_module); | |
| } | |
| } | |
| Py_XDECREF(capsule); | |
| } | |
| } | |
| static void __Pyx_FastGilFuncInit0(void) { | |
| } | |
| static void __Pyx_FastGilFuncInit(void) { | |
| struct __Pyx_FastGilVtab* shared = (struct __Pyx_FastGilVtab*)PyCapsule_Import(__Pyx_FastGIL_PyCapsule, 1); | |
| if (shared) { | |
| __Pyx_FastGilFuncs = *shared; | |
| } else { | |
| PyErr_Clear(); | |
| __Pyx_FastGilFuncInit0(); | |
| } | |
| } | |
| ///////////////////// PretendToInitialize //////////////////////// | |
| // In C++ a variable must actually be initialized to make returning | |
| // it defined behaviour, and there doesn't seem to be a viable compiler trick to | |
| // avoid that. | |
| template <typename T> | |
| static void __Pyx_pretend_to_initialize(T* ptr) { | |
| // In C++11 we have enough introspection to work out which types it's actually | |
| // necessary to apply this to (non-trivial types will have been initialized by | |
| // the definition). Below C++11 just initialize everything. | |
| if ((std::is_trivially_default_constructible<T>::value)) | |
| *ptr = T(); | |
| (void)ptr; | |
| } | |
| // For C, taking an address of a variable is enough to make returning it | |
| // defined behaviour. | |
| static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } | |
| ///////////////////// UtilityCodePragmas ///////////////////////// | |
| /* Warning 4127: conditional expression is constant | |
| * Cython uses constant conditional expressions to allow in inline functions to be optimized at | |
| * compile-time, so this warning is not useful | |
| */ | |
| ///////////////////// UtilityCodePragmasEnd ////////////////////// | |
| //////////////////// NewCodeObj.proto //////////////////////// | |
| //@proto_block: init_codeobjects | |
| static PyObject* __Pyx_PyCode_New( | |
| //int argcount, | |
| //int num_posonly_args, | |
| //int num_kwonly_args, | |
| //int nlocals, | |
| // int s, | |
| //int flags, | |
| //int first_line, | |
| const __Pyx_PyCode_New_function_description descr, | |
| // PyObject *code, | |
| // PyObject *consts, | |
| // PyObject* n, | |
| // PyObject *varnames_tuple, | |
| PyObject * const *varnames, | |
| // PyObject *freevars, | |
| // PyObject *cellvars, | |
| PyObject *filename, | |
| PyObject *funcname, | |
| const char *line_table, | |
| PyObject *tuple_dedup_map | |
| );/*proto*/ | |
| //////////////////// NewCodeObj //////////////////////// | |
| // Note that the limited API doesn't know about PyCodeObject, so the type of this | |
| // is PyObject (unlike for the main API) | |
| static PyObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f, | |
| PyObject *code, PyObject *c, PyObject* n, PyObject *v, | |
| PyObject *fv, PyObject *cell, PyObject* fn, | |
| PyObject *name, int fline, PyObject *lnos) { | |
| // Backup option for generating a code object. | |
| // PyCode_NewEmpty isn't in the limited API. Therefore the two options are | |
| // 1. Python call of the code type with a long list of positional args. | |
| // 2. Generate a code object by compiling some trivial code, and customize. | |
| // We use the first option here. | |
| PyObject *exception_table = NULL; | |
| PyObject *types_module=NULL, *code_type=NULL, *result=NULL; | |
| PyObject *version_info; /* borrowed */ | |
| PyObject *py_minor_version = NULL; | |
| long minor_version = 0; | |
| PyObject *type, *value, *traceback; | |
| // we must be able to call this while an exception is happening - thus clear then restore the state | |
| PyErr_Fetch(&type, &value, &traceback); | |
| minor_version = 11; | |
| // we don't yet need to distinguish between versions > 11 | |
| // Note that from 3.13, when we do, we can use Py_Version | |
| if (!(version_info = PySys_GetObject("version_info"))) goto end; | |
| if (!(py_minor_version = PySequence_GetItem(version_info, 1))) goto end; | |
| minor_version = PyLong_AsLong(py_minor_version); | |
| Py_DECREF(py_minor_version); | |
| if (minor_version == -1 && PyErr_Occurred()) goto end; | |
| if (!(types_module = PyImport_ImportModule("types"))) goto end; | |
| if (!(code_type = PyObject_GetAttrString(types_module, "CodeType"))) goto end; | |
| if (minor_version <= 7) { | |
| // 3.7: | |
| // code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring, | |
| // constants, names, varnames, filename, name, firstlineno, | |
| // lnotab[, freevars[, cellvars]]) | |
| (void)p; | |
| result = PyObject_CallFunction(code_type, "iiiiiOOOOOOiOOO", a, k, l, s, f, code, | |
| c, n, v, fn, name, fline, lnos, fv, cell); | |
| } else if (minor_version <= 10) { | |
| // 3.8, 3.9, 3.10 | |
| // code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, | |
| // flags, codestring, constants, names, varnames, filename, name, | |
| // firstlineno, lnotab[, freevars[, cellvars]]) | |
| // 3.10 switches lnotab for linetable, but is otherwise the same | |
| result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOiOOO", a,p, k, l, s, f, code, | |
| c, n, v, fn, name, fline, lnos, fv, cell); | |
| } else { | |
| // 3.11, 3.12 | |
| // code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, | |
| // flags, codestring, constants, names, varnames, filename, name, | |
| // qualname, firstlineno, linetable, exceptiontable, freevars=(), cellvars=(), /) | |
| // We use name and qualname for simplicity | |
| if (!(exception_table = PyBytes_FromStringAndSize(NULL, 0))) goto end; | |
| result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOOiOOOO", a,p, k, l, s, f, code, | |
| c, n, v, fn, name, name, fline, lnos, exception_table, fv, cell); | |
| } | |
| end: | |
| Py_XDECREF(code_type); | |
| Py_XDECREF(exception_table); | |
| Py_XDECREF(types_module); | |
| if (type) { | |
| PyErr_Restore(type, value, traceback); | |
| } | |
| return result; | |
| } | |
| static PyCodeObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f, | |
| PyObject *code, PyObject *c, PyObject* n, PyObject *v, | |
| PyObject *fv, PyObject *cell, PyObject* fn, | |
| PyObject *name, int fline, PyObject *lnos) { | |
| // As earlier versions, but | |
| // 1. pass an empty bytes string as exception_table | |
| // 2. pass name as qualname (TODO this might implementing properly in future) | |
| PyCodeObject *result; | |
| result = | |
| PyUnstable_Code_NewWithPosOnlyArgs | |
| PyCode_NewWithPosOnlyArgs | |
| (a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, name, fline, lnos, EMPTY(bytes)); | |
| if (likely(result)) | |
| result->_co_firsttraceable = 0; | |
| return result; | |
| } | |
| // This is a specialised helper function for creating Cython's function code objects. | |
| // It only receives the arguments that differ between the Cython functions of the module. | |
| // This minimises the calling code in the module init function. | |
| static PyObject* __Pyx_PyCode_New( | |
| //int argcount, | |
| //int num_posonly_args, | |
| //int num_kwonly_args, | |
| //int nlocals, | |
| // int s, | |
| //int flags, | |
| //int first_line, | |
| const __Pyx_PyCode_New_function_description descr, | |
| // PyObject *code, | |
| // PyObject *consts, | |
| // PyObject* n, | |
| // PyObject *varnames_tuple, | |
| PyObject * const *varnames, | |
| // PyObject *freevars, | |
| // PyObject *cellvars, | |
| PyObject *filename, | |
| PyObject *funcname, | |
| // line table replaced lnotab in Py3.11 (PEP-626) | |
| const char *line_table, | |
| PyObject *tuple_dedup_map | |
| ) { | |
| PyObject *code_obj = NULL, *varnames_tuple_dedup = NULL, *code_bytes = NULL, *line_table_bytes = NULL; | |
| Py_ssize_t var_count = (Py_ssize_t) descr.nlocals; | |
| PyObject *varnames_tuple = PyTuple_New(var_count); | |
| if (unlikely(!varnames_tuple)) return NULL; | |
| for (Py_ssize_t i=0; i < var_count; i++) { | |
| Py_INCREF(varnames[i]); | |
| if (__Pyx_PyTuple_SET_ITEM(varnames_tuple, i, varnames[i]) != (0)) goto done; | |
| } | |
| varnames_tuple_dedup = PyDict_GetItem(tuple_dedup_map, varnames_tuple); | |
| if (!varnames_tuple_dedup) { | |
| if (unlikely(PyDict_SetItem(tuple_dedup_map, varnames_tuple, varnames_tuple) < 0)) goto done; | |
| varnames_tuple_dedup = varnames_tuple; | |
| } | |
| varnames_tuple_dedup = PyDict_SetDefault(tuple_dedup_map, varnames_tuple, varnames_tuple); | |
| if (unlikely(!varnames_tuple_dedup)) goto done; | |
| Py_INCREF(varnames_tuple_dedup); | |
| if (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table != NULL | |
| && !CYTHON_COMPILING_IN_GRAAL) { | |
| line_table_bytes = PyBytes_FromStringAndSize(line_table, descr.line_table_length); | |
| if (unlikely(!line_table_bytes)) goto done; | |
| // Allocate a "byte code" array (oversized) to match the addresses in the line table. | |
| // Length and alignment must be a multiple of sizeof(_Py_CODEUNIT), which is CPython specific but currently 2. | |
| // CPython makes a copy of the code array internally, so make sure it's somewhat short (but not too short). | |
| Py_ssize_t code_len = (descr.line_table_length * 2 + 4) & ~3; | |
| code_bytes = PyBytes_FromStringAndSize(NULL, code_len); | |
| if (unlikely(!code_bytes)) goto done; | |
| char* c_code_bytes = PyBytes_AsString(code_bytes); | |
| if (unlikely(!c_code_bytes)) goto done; | |
| // We initialise the code array to '\0' even though a NOP would be more accurate, | |
| // but NOP changes its byte code ID across Python versions/implementations. | |
| memset(c_code_bytes, 0, (size_t) code_len); | |
| } | |
| code_obj = (PyObject*) __Pyx__PyCode_New( | |
| (int) descr.argcount, | |
| (int) descr.num_posonly_args, | |
| (int) descr.num_kwonly_args, | |
| (int) descr.nlocals, | |
| 0, | |
| (int) descr.flags, | |
| code_bytes ? code_bytes : EMPTY(bytes), | |
| EMPTY(tuple), | |
| EMPTY(tuple), | |
| varnames_tuple_dedup, | |
| EMPTY(tuple), | |
| EMPTY(tuple), | |
| filename, | |
| funcname, | |
| (int) descr.first_line, | |
| (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table_bytes) ? line_table_bytes : EMPTY(bytes) | |
| ); | |
| done: | |
| Py_XDECREF(code_bytes); | |
| Py_XDECREF(line_table_bytes); | |
| Py_XDECREF(varnames_tuple_dedup); | |
| Py_DECREF(varnames_tuple); | |
| return code_obj; | |
| } | |
| ////////////////////////// MultiPhaseInitModuleState.proto ///////////// | |
| // This defines an ad-hoc, single module version of PyState_FindModule that | |
| // works for multi-phase init modules. It's intended to be the last option | |
| // when all the other official ways of getting the module are unavailable. | |
| static PyObject *__Pyx_State_FindModule(void*); /* proto */ | |
| static int __Pyx_State_AddModule(PyObject* module, void*); /* proto */ | |
| static int __Pyx_State_RemoveModule(void*); /* proto */ | |
| ////////////////////////// MultiPhaseInitModuleState ///////////// | |
| //@requires: Synchronization.c::Atomics | |
| // Code to maintain a mapping between (sub)interpreters and the module instance that they imported. | |
| // This is used to find the correct module state for the current interpreter. | |
| // If you're using multiple interpreters but a single GIL then | |
| // this can be undefined for a bit of speed. | |
| // Isolated subinterpreters were added in 3.12, and nogil in 3.13, so before that | |
| // we can safely assume that we're protected by the GIL. | |
| // TODO - turn this off as appropriate when the user is able to set | |
| // Py_MOD_PER_INTERPRETER_GIL_SUPPORTED explicitly. | |
| // We also need a lock. In order of preference: | |
| // - PyMutex | |
| // - a language standard library | |
| // - pthreads | |
| // - msvc | |
| // - PyThread_lock isn't acceptable since we can't initialize it in a thread safe way | |
| static PyMutex __Pyx_ModuleStateLookup_mutex = {0}; | |
| static std::mutex __Pyx_ModuleStateLookup_mutex; | |
| static mtx_t __Pyx_ModuleStateLookup_mutex; | |
| static once_flag __Pyx_ModuleStateLookup_mutex_once_flag = ONCE_FLAG_INIT; | |
| static void __Pyx_ModuleStateLookup_initialize_mutex(void) { | |
| mtx_init(&__Pyx_ModuleStateLookup_mutex, mtx_plain); | |
| } | |
| // HAVE_PTHREAD_H comes from pyconfig.h | |
| static pthread_mutex_t __Pyx_ModuleStateLookup_mutex = PTHREAD_MUTEX_INITIALIZER; | |
| // Using a slim-read-write lock (instead of a mutex/critical section) | |
| // because it can be statically initialized. | |
| static SRWLOCK __Pyx_ModuleStateLookup_mutex = SRWLOCK_INIT; | |
| typedef struct { | |
| int64_t id; | |
| PyObject *module; | |
| } __Pyx_InterpreterIdAndModule; | |
| typedef struct { | |
| char interpreter_id_as_index; | |
| Py_ssize_t count; | |
| Py_ssize_t allocated; | |
| __Pyx_InterpreterIdAndModule table[1]; | |
| } __Pyx_ModuleStateLookupData; | |
| // "interpreter_id_as_index" above means "the maximum interpreter ID ever seen is smaller than | |
| // __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE and thus they're stored in an array | |
| // where the index corresponds to interpreter ID, and __Pyx_ModuleStateLookup_count | |
| // is the size of the array. | |
| static __pyx_atomic_int_type __Pyx_ModuleStateLookup_read_counter = 0; | |
| // A sorted list of (sub)interpreter IDs and the module that was imported into that interpreter. | |
| // For now look this up via binary search. | |
| static __pyx_atomic_ptr_type __Pyx_ModuleStateLookup_data = 0; | |
| static __Pyx_ModuleStateLookupData* __Pyx_ModuleStateLookup_data = NULL; | |
| static __Pyx_InterpreterIdAndModule* __Pyx_State_FindModuleStateLookupTableLowerBound( | |
| __Pyx_InterpreterIdAndModule* table, | |
| Py_ssize_t count, | |
| int64_t interpreterId) { | |
| __Pyx_InterpreterIdAndModule* begin = table; | |
| __Pyx_InterpreterIdAndModule* end = begin + count; | |
| // fairly likely - e.g. single interpreter | |
| if (begin->id == interpreterId) { | |
| return begin; | |
| } | |
| while ((end - begin) > __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) { | |
| __Pyx_InterpreterIdAndModule* halfway = begin + (end - begin)/2; | |
| if (halfway->id == interpreterId) { | |
| return halfway; | |
| } | |
| if (halfway->id < interpreterId) { | |
| begin = halfway; | |
| } else { | |
| end = halfway; | |
| } | |
| } | |
| // Assume that for small ranges, it's quicker to do a linear search | |
| for (; begin < end; ++begin) { | |
| if (begin->id >= interpreterId) return begin; | |
| } | |
| return begin; | |
| } | |
| static PyObject *__Pyx_State_FindModule(CYTHON_UNUSED void* dummy) { | |
| int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); | |
| if (interpreter_id == -1) return NULL; | |
| __Pyx_ModuleStateLookupData* data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data); | |
| { | |
| // Thread sanitizer says that this is OK relaxed, but I think it needs to be acquire-release | |
| __pyx_atomic_incr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); | |
| // data == NULL can either mean we're writing, or it's uninitialized. | |
| // Uninitialized only happens infrequently on the first few calls, so it's fine | |
| // to be on the slow path. | |
| if (likely(data)) { | |
| __Pyx_ModuleStateLookupData* new_data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_acquire(&__Pyx_ModuleStateLookup_data); | |
| if (likely(data == new_data)) { | |
| // Nothing has written the data between incrementing the read counter and loading the pointer. | |
| goto read_finished; | |
| } | |
| } | |
| // In principle DW believes this could be "relaxed", but it's on the unlikely slow path anyway | |
| // so let's not add more macros. | |
| // Undo our addition to the read counter. | |
| __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); | |
| // Wait for the write to finish and try again | |
| __Pyx_ModuleStateLookup_Lock(); | |
| __pyx_atomic_incr_relaxed(&__Pyx_ModuleStateLookup_read_counter); | |
| data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data); | |
| __Pyx_ModuleStateLookup_Unlock(); | |
| } | |
| read_finished:; | |
| __Pyx_ModuleStateLookupData* data = __Pyx_ModuleStateLookup_data; | |
| __Pyx_InterpreterIdAndModule* found = NULL; | |
| // There's one "already imported" check that'll hit this | |
| if (unlikely(!data)) goto end; | |
| if (data->interpreter_id_as_index) { | |
| if (interpreter_id < data->count) { | |
| found = data->table+interpreter_id; | |
| } | |
| } else { | |
| found = __Pyx_State_FindModuleStateLookupTableLowerBound( | |
| data->table, data->count, interpreter_id); | |
| } | |
| end: | |
| { | |
| PyObject *result=NULL; | |
| if (found && found->id == interpreter_id) { | |
| result = found->module; | |
| } | |
| __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); | |
| return result; | |
| } | |
| } | |
| static void __Pyx_ModuleStateLookup_wait_until_no_readers(void) { | |
| // Wait for any readers still working on the old data. Spin-lock is | |
| // fine because readers should be much faster than memory allocation. | |
| while (__pyx_atomic_load(&__Pyx_ModuleStateLookup_read_counter) != 0); | |
| } | |
| static int __Pyx_State_AddModuleInterpIdAsIndex(__Pyx_ModuleStateLookupData **old_data, PyObject* module, int64_t interpreter_id) { | |
| Py_ssize_t to_allocate = (*old_data)->allocated; | |
| while (to_allocate <= interpreter_id) { | |
| if (to_allocate == 0) to_allocate = 1; | |
| else to_allocate *= 2; | |
| } | |
| __Pyx_ModuleStateLookupData *new_data = *old_data; | |
| if (to_allocate != (*old_data)->allocated) { | |
| new_data = (__Pyx_ModuleStateLookupData *)realloc( | |
| *old_data, | |
| sizeof(__Pyx_ModuleStateLookupData)+(to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule)); | |
| if (!new_data) { | |
| PyErr_NoMemory(); | |
| return -1; | |
| } | |
| for (Py_ssize_t i = new_data->allocated; i < to_allocate; ++i) { | |
| new_data->table[i].id = i; | |
| new_data->table[i].module = NULL; | |
| } | |
| new_data->allocated = to_allocate; | |
| } | |
| new_data->table[interpreter_id].module = module; | |
| if (new_data->count < interpreter_id+1) { | |
| new_data->count = interpreter_id+1; | |
| } | |
| *old_data = new_data; | |
| return 0; | |
| } | |
| static void __Pyx_State_ConvertFromInterpIdAsIndex(__Pyx_ModuleStateLookupData *data) { | |
| __Pyx_InterpreterIdAndModule *read = data->table; | |
| __Pyx_InterpreterIdAndModule *write = data->table; | |
| __Pyx_InterpreterIdAndModule *end = read + data->count; | |
| for (; read<end; ++read) { | |
| if (read->module) { | |
| write->id = read->id; | |
| write->module = read->module; | |
| ++write; | |
| } | |
| // Otherwise empty; don't copy | |
| } | |
| data->count = write - data->table; | |
| for (; write<end; ++write) { | |
| // clear rest of array | |
| write->id = 0; | |
| write->module = NULL; | |
| } | |
| data->interpreter_id_as_index = 0; | |
| } | |
| static int __Pyx_State_AddModule(PyObject* module, CYTHON_UNUSED void* dummy) { | |
| int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); | |
| if (interpreter_id == -1) return -1; | |
| int result = 0; | |
| __Pyx_ModuleStateLookup_Lock(); | |
| // Adding modules is the slow path so I've not thought about memory ordering much and | |
| // just made it strict. | |
| // we're working and maybe modifying it, swap for 0 | |
| __Pyx_ModuleStateLookupData *old_data = (__Pyx_ModuleStateLookupData *) | |
| __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0); | |
| __Pyx_ModuleStateLookupData *old_data = __Pyx_ModuleStateLookup_data; | |
| __Pyx_ModuleStateLookupData *new_data = old_data; | |
| if (!new_data) { | |
| // If we don't yet have anything, initialize | |
| new_data = (__Pyx_ModuleStateLookupData *)calloc(1, sizeof(__Pyx_ModuleStateLookupData)); | |
| if (!new_data) { | |
| result = -1; | |
| PyErr_NoMemory(); | |
| goto end; | |
| } | |
| new_data->allocated = 1; | |
| new_data->interpreter_id_as_index = 1; | |
| } | |
| // Pretty much everything from here modifies the data, and so requires us to wait | |
| // until all existing readers have finished in order to be thread-safe. | |
| __Pyx_ModuleStateLookup_wait_until_no_readers(); | |
| if (new_data->interpreter_id_as_index) { | |
| if (interpreter_id < __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) { | |
| result = __Pyx_State_AddModuleInterpIdAsIndex(&new_data, module, interpreter_id); | |
| goto end; | |
| } | |
| // otherwise we have to convert then proceed with a normal insertion | |
| __Pyx_State_ConvertFromInterpIdAsIndex(new_data); | |
| } | |
| { | |
| Py_ssize_t insert_at = 0; | |
| { | |
| __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound( | |
| new_data->table, new_data->count, interpreter_id); | |
| assert(lower_bound); | |
| insert_at = lower_bound - new_data->table; | |
| if (unlikely(insert_at < new_data->count && lower_bound->id == interpreter_id)) { | |
| lower_bound->module = module; | |
| goto end; // already in table, nothing more to do | |
| } | |
| } | |
| if (new_data->count+1 >= new_data->allocated) { | |
| // Use C realloc. PyMem_RawMalloc is added to the limited API fairly late (3.13) | |
| // and we want allocation independent of the interpreter which I think excludes PyMem_Malloc. | |
| Py_ssize_t to_allocate = (new_data->count+1)*2; | |
| new_data = | |
| (__Pyx_ModuleStateLookupData*)realloc( | |
| new_data, | |
| sizeof(__Pyx_ModuleStateLookupData) + | |
| (to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule)); | |
| if (!new_data) { | |
| result = -1; | |
| new_data = old_data; | |
| PyErr_NoMemory(); | |
| goto end; | |
| } | |
| new_data->allocated = to_allocate; | |
| } | |
| ++new_data->count; | |
| int64_t last_id = interpreter_id; | |
| PyObject *last_module = module; | |
| for (Py_ssize_t i=insert_at; i<new_data->count; ++i) { | |
| int64_t current_id = new_data->table[i].id; | |
| new_data->table[i].id = last_id; | |
| last_id = current_id; | |
| PyObject *current_module = new_data->table[i].module; | |
| new_data->table[i].module = last_module; | |
| last_module = current_module; | |
| } | |
| } | |
| end: | |
| __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, new_data); | |
| __Pyx_ModuleStateLookup_data = new_data; | |
| __Pyx_ModuleStateLookup_Unlock(); | |
| return result; | |
| } | |
| static int __Pyx_State_RemoveModule(CYTHON_UNUSED void* dummy) { | |
| int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); | |
| if (interpreter_id == -1) return -1; | |
| __Pyx_ModuleStateLookup_Lock(); | |
| __Pyx_ModuleStateLookupData *data = (__Pyx_ModuleStateLookupData *) | |
| __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0); | |
| __Pyx_ModuleStateLookupData *data = __Pyx_ModuleStateLookup_data; | |
| if (data->interpreter_id_as_index) { | |
| if (interpreter_id < data->count) { | |
| data->table[interpreter_id].module = NULL; | |
| } | |
| goto done; | |
| } | |
| { | |
| __Pyx_ModuleStateLookup_wait_until_no_readers(); | |
| __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound( | |
| data->table, data->count, interpreter_id); | |
| // TODO Errors here? | |
| if (!lower_bound) goto done; | |
| if (lower_bound->id != interpreter_id) goto done; | |
| __Pyx_InterpreterIdAndModule *end = data->table+data->count; | |
| for (;lower_bound<end-1; ++lower_bound) { | |
| lower_bound->id = (lower_bound+1)->id; | |
| lower_bound->module = (lower_bound+1)->module; | |
| } | |
| } | |
| --data->count; | |
| if (data->count == 0) { | |
| free(data); | |
| data = NULL; | |
| } | |
| // For now, never shrink the allocated table. | |
| done: | |
| __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, data); | |
| __Pyx_ModuleStateLookup_data = data; | |
| __Pyx_ModuleStateLookup_Unlock(); | |
| return 0; | |
| } | |
| ////////////////////// IncludeStdlibH.proto ////////////////////// | |