From a224a0f0e3cb43958cc0e5710fdbde6e8c8c4333 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Fri, 17 Apr 2026 16:44:55 +0200 Subject: [PATCH 1/2] Initial attempt to incooperrate tracing regions --- README.md | 7 ++++++ src/bocpy/_core.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2cba001..0fe962f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ + +../cpython/python.exe -m venv .venvpyrona +source .venvpyrona/bin/activate.fish +pip install -e . --verbose + +--- + # bocpy ![BOC Logo](http://microsoft.github.io/bocpy/images/logo.svg) diff --git a/src/bocpy/_core.c b/src/bocpy/_core.c index 279c953..2e006a1 100644 --- a/src/bocpy/_core.c +++ b/src/bocpy/_core.c @@ -123,6 +123,8 @@ static inline void boc_park_wait(BOCQueue *q); #if PY_VERSION_HEX >= 0x030D0000 #define Py_BUILD_CORE #include +#include +#define Region_Check(x) Py_IS_TYPE((x), &_PyTracingRegion_Type) #endif const struct timespec SLEEP_TS = {0, 1000}; @@ -656,6 +658,8 @@ static thread_local _core_module_state *BOC_STATE; BOC_STATE = (_core_module_state *)PyModule_GetState(m); \ } while (0) +#define BOC_TRACE + #ifdef BOC_TRACE static inline void print_obj_debug(PyObject *obj) { PyObject_Print(obj, stdout, 0); @@ -830,6 +834,20 @@ static PyObject *xidata_to_object(XIDATA_T *xidata, bool pickled) { return value; } +static PyObject *xidata_to_region(XIDATA_T *xidata) { + assert(xidata != NULL); + assert(Region_Check(xidata->obj)); + assert(xidata->data == NULL); + + PyObject* region = xidata->obj; + if (_PyTracingRegion_Open(region)) { + return NULL; + } + xidata->obj = NULL; + + return region; +} + /// @brief Serializes an object as xidata /// @param module The _core module /// @param contents The value to serialize @@ -876,6 +894,24 @@ static PyObject *object_to_xidata(PyObject *value, XIDATA_T **xidata_ptr) { return NULL; } +static PyObject *region_to_xidata(PyObject *value, XIDATA_T **xidata_ptr) { + assert(Region_Check(value)); + assert(*xidata_ptr == NULL); + + *xidata_ptr = XIDATA_NEW(); + XIDATA_T *xidata = *xidata_ptr; + + if (xidata == NULL) { + PyErr_NoMemory(); + return NULL; + } + + xidata->data = NULL; + xidata->obj = Py_NewRef(value); + + Py_RETURN_TRUE; +} + /// @brief The threadsafe cown object. /// @details This can be safely referenced and used from multiple processes. typedef struct boc_cown { @@ -1417,7 +1453,11 @@ static int cown_acquire(BOCCown *cown) { assert(cown->value == NULL); assert(cown->xidata != NULL); - cown->value = xidata_to_object(cown->xidata, cown->pickled); + if (cown->xidata->data == NULL && cown->xidata->obj && Region_Check(cown->xidata->obj)) { + cown->value = xidata_to_region(cown->xidata); + } else { + cown->value = xidata_to_object(cown->xidata, cown->pickled); + } if (cown->value == NULL) { return -1; @@ -1469,7 +1509,26 @@ static int cown_release(BOCCown *cown) { assert(cown->value != NULL); assert(cown->xidata == NULL); - PyObject *pickled = object_to_xidata(cown->value, &cown->xidata); + PyObject *pickled = NULL; + + // Tracing regions can only be shared via cowns, since they require a thread + // safe container with an owning reference. This would not be a given if + // this check is build into `object_to_xidata` + if (Region_Check(cown->value)) { + int close_res = _PyTracingRegion_Close(cown->value); + if (close_res < 0) { + return -1; + } + if (close_res == 0) { + PyErr_Format( + PyExc_RuntimeError, + "the cown can't be released, since the contained region is still open"); + return -1; + } + pickled = region_to_xidata(cown->value, &cown->xidata); + } else { + pickled = object_to_xidata(cown->value, &cown->xidata); + } if (pickled == NULL) { return -1; From 72d56a5a6f18317aad172260afe58ef181e722a5 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Wed, 6 May 2026 17:18:59 +0200 Subject: [PATCH 2/2] Tiny fixes --- src/bocpy/_core.c | 4 +--- src/bocpy/_math.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bocpy/_core.c b/src/bocpy/_core.c index 2e006a1..162215c 100644 --- a/src/bocpy/_core.c +++ b/src/bocpy/_core.c @@ -658,8 +658,6 @@ static thread_local _core_module_state *BOC_STATE; BOC_STATE = (_core_module_state *)PyModule_GetState(m); \ } while (0) -#define BOC_TRACE - #ifdef BOC_TRACE static inline void print_obj_debug(PyObject *obj) { PyObject_Print(obj, stdout, 0); @@ -840,10 +838,10 @@ static PyObject *xidata_to_region(XIDATA_T *xidata) { assert(xidata->data == NULL); PyObject* region = xidata->obj; + xidata->obj = NULL; if (_PyTracingRegion_Open(region)) { return NULL; } - xidata->obj = NULL; return region; } diff --git a/src/bocpy/_math.c b/src/bocpy/_math.c index b8607be..a0c9ac1 100644 --- a/src/bocpy/_math.c +++ b/src/bocpy/_math.c @@ -1927,7 +1927,7 @@ static PyGetSetDef Matrix_getset[] = { {NULL} /* Sentinel */ }; -inline enum BinaryOps swap_right(enum BinaryOps op) { +static inline enum BinaryOps swap_right(enum BinaryOps op) { switch (op) { case Subtract: return RSubtract;