1919#include "pyerrors.h"
2020#include "pystate.h"
2121
22+ // Needed to test for region object
23+ extern PyTypeObject PyRegion_Type ;
24+ extern PyTypeObject PyCown_Type ;
25+
2226typedef enum {
2327 Cown_RELEASED = 0 ,
2428 Cown_ACQUIRED = 1 ,
@@ -57,7 +61,7 @@ static void PyCown_dealloc(PyCownObject *self) {
5761}
5862
5963static int PyCown_init (PyCownObject * self , PyObject * args , PyObject * kwds ) {
60- // TODO: should not be needed in the future
64+ // TODO: Pyrona: should not be needed in the future
6165 _Py_MakeImmutable (_PyObject_CAST (Py_TYPE (self )));
6266 _Py_notify_regions_in_use ();
6367
@@ -128,10 +132,12 @@ static int PyCown_traverse(PyCownObject *self, visitproc visit, void *arg) {
128132// compatible with PyCFunction
129133static PyObject * PyCown_acquire (PyCownObject * self , PyObject * ignored ) {
130134 PyThreadState * tstate = PyThreadState_Get ();
135+
136+ // TODO: Pyrona: releasing the GIL will eventually not be necessary here
131137 Py_BEGIN_ALLOW_THREADS
132138 int expected = Cown_RELEASED ;
133139
134- // TODO: eventually replace this with something from pycore_atomic (nothing there now)
140+ // TODO: Pyrona: eventually replace this with something from pycore_atomic (nothing there now)
135141 while (!atomic_compare_exchange_strong (& self -> state ._value , & expected , Cown_ACQUIRED )) {
136142 expected = Cown_RELEASED ;
137143 sem_wait (& self -> semaphore );
@@ -155,11 +161,16 @@ static PyObject *PyCown_release(PyCownObject *self, PyObject *ignored) {
155161
156162 BAIL_UNLESS_OWNED (self , "Thread attempted to release a cown it did not own" );
157163
158- Py_BEGIN_ALLOW_THREADS
164+ if (self -> value && Py_TYPE (self -> value ) == & PyRegion_Type ) {
165+ if (PyCown_close_region (self -> value ) == NULL ) {
166+ // Close region failed -- propagate its error
167+ return NULL ;
168+ }
169+ }
170+
159171 self -> owning_thread = 0 ;
160172 _Py_atomic_store (& self -> state , Cown_RELEASED );
161173 sem_post (& self -> semaphore );
162- Py_END_ALLOW_THREADS
163174
164175 Py_RETURN_NONE ;
165176}
@@ -174,6 +185,13 @@ int _PyCown_is_released(PyObject *self) {
174185 return STATE (cown ) == Cown_RELEASED ;
175186}
176187
188+ int _PyCown_is_pending_release (PyObject * self ) {
189+ assert (Py_TYPE (self ) == & PyCown_Type && "Is pending release called on non-cown!" );
190+
191+ PyCownObject * cown = _Py_CAST (PyCownObject * , self );
192+ return STATE (cown ) == Cown_PENDING_RELEASE ;
193+ }
194+
177195// The ignored argument is required for this function's type to be
178196// compatible with PyCFunction
179197static PyObject * PyCown_get (PyCownObject * self , PyObject * ignored ) {
@@ -186,16 +204,12 @@ static PyObject *PyCown_get(PyCownObject *self, PyObject *ignored) {
186204 }
187205}
188206
189- // Needed to test for region object
190- extern PyTypeObject PyRegion_Type ;
191- extern PyTypeObject PyCown_Type ;
192-
193207static PyObject * PyCown_set_unchecked (PyCownObject * self , PyObject * arg ) {
194208 // Cowns are cells that hold a reference to a bridge object,
195209 // (or another cown or immutable object)
196- const bool is_region_object =
210+ const bool arg_is_region_object =
197211 Py_IS_TYPE (arg , & PyRegion_Type ) && _Py_is_bridge_object (arg );
198- if (is_region_object ||
212+ if (arg_is_region_object ||
199213 arg -> ob_type == & PyCown_Type ||
200214 _Py_IsImmutable (arg )) {
201215
@@ -205,10 +219,14 @@ static PyObject *PyCown_set_unchecked(PyCownObject *self, PyObject *arg) {
205219
206220 // Tell the region that it is owned by a cown,
207221 // to enable it to release the cown on close
208- if (is_region_object ) {
222+ if (arg_is_region_object ) {
209223 _PyRegion_set_cown_parent (arg , _PyObject_CAST (self ));
224+ // TODO: Pyrona: should not run try close here unless dirty at the end of phase 3
225+ // if (_PyCown_close_region(arg) == Py_None) {
210226 if (_PyRegion_is_closed (arg )) {
211- PyCown_release (self , NULL );
227+ if (PyCown_release (self , NULL ) == NULL ) {
228+ PyErr_Clear ();
229+ }
212230 } else {
213231 _Py_atomic_store (& self -> state , Cown_PENDING_RELEASE );
214232 PyThreadState * tstate = PyThreadState_Get ();
0 commit comments