Commits

Trent Nelson committed 99a1855 Draft

Implement a way to override an object's initial type object.

Initial use: intercept tp_dealloc with our custom _PyObject_Dealloc
that takes care of closing an object's event (if applicable).

Comments (0)

Files changed (3)

     size_t  px_flags;                   \
     void   *srw_lock;                   \
     void   *event;                      \
+    struct _typeobject *orig_type;      \
     struct _object *_ob_next;           \
     struct _object *_ob_prev;
 
     0,                                  \
     NULL,                               \
     NULL,                               \
+    NULL,                               \
     (struct _object *)_Py_NOT_PARALLEL, \
     (struct _object *)_Py_NOT_PARALLEL,
 #endif /* WITH_PARALLEL */
 
 #define Py_REFCNT(ob)           (((PyObject*)(ob))->ob_refcnt)
 #define Py_TYPE(ob)             (((PyObject*)(ob))->ob_type)
+#define Py_ORIG_TYPE(ob)        (((PyObject*)(ob))->orig_type)
 #define Py_SIZE(ob)             (((PyVarObject*)(ob))->ob_size)
 
 /********************* String Literals ****************************************/

Include/objimpl.h

     assert(Py_TYPE(op));
     op->is_px = _Py_NOT_PARALLEL;
     op->px    = _Py_NOT_PARALLEL;
-    op->px_flags = 0;
-    op->srw_lock = NULL;
-    op->event    = NULL;
+    op->px_flags  = 0;
+    op->srw_lock  = NULL;
+    op->event     = NULL;
+    op->orig_type = NULL;
 #ifdef Py_TRACE_REFS
     op->_ob_next = NULL;
     op->_ob_prev = NULL;

Python/pyparallel.c

         _PyParallel_DisassociateCurrentThreadFromCallback();
 }
 
-
 __inline
 void *
 _PyHeap_MemAlignedMalloc(Context *c, size_t n)
     return active;
 }
 
+static void
+_PyObject_Dealloc(PyObject *o)
+{
+    PyTypeObject *tp;
+#ifdef Py_DEBUG
+    Py_GUARD_OBJ(o);
+    Py_GUARD
+#endif
+    assert(Py_ORIG_TYPE(o));
+    assert(
+        Py_PXFLAGS(o) & (
+            Py_PXFLAGS_EVENT
+        )
+    );
+
+    if (Py_HAS_EVENT(o))
+        PyEvent_DESTROY(o);
+
+    tp = Py_TYPE(o);
+    Py_TYPE(o) = Py_ORIG_TYPE(o);
+    Py_ORIG_TYPE(o) = NULL;
+    (*Py_TYPE(o)->tp_dealloc)(o);
+    PyMem_FREE(tp);
+}
+
 __inline
 char
 _protected(PyObject *obj)
     Py_RETURN_BOOL(_try_write_lock(obj));
 }
 
-__inline
+char
+_PyObject_PrepOrigType(PyObject *o)
+{
+    PyTypeObject *tp = Py_ORIG_TYPE(o);
+    if (!tp) {
+        tp = (PyTypeObject *)PyMem_MALLOC(sizeof(PyTypeObject));
+        if (!tp) {
+            PyErr_NoMemory();
+            return 0;
+        }
+        memcpy(tp, Py_TYPE(o), sizeof(PyTypeObject));
+        Py_ORIG_TYPE(o) = Py_TYPE(o);
+        Py_TYPE(o) = tp;
+        tp->tp_dealloc = _PyObject_Dealloc;
+    }
+
+    assert(Py_ORIG_TYPE(o));
+    assert(Py_ORIG_TYPE(o)->tp_dealloc);
+    assert(Py_ORIG_TYPE(o)->tp_dealloc != _PyObject_Dealloc);
+    assert(Py_TYPE(o)->tp_dealloc == _PyObject_Dealloc);
+    return 1;
+}
+
 char
 _PyEvent_TryCreate(PyObject *o)
 {
         success = 0;
         if (Py_ISPX(o))
             PyErr_SetNone(PyExc_WaitError);
+        else if (!_PyObject_PrepOrigType(o))
+            goto done;
         else if (!PyEvent_CREATE(o))
             PyErr_SetFromWindowsErr(0);
         else {
             success = 1;
         }
     }
+done:
+    if (!success)
+        assert(PyErr_Occurred());
     _write_unlock(o);
     return success;
 }
 
     Py_EVENT(n) = NULL;
     Py_PXFLAGS(n) = Py_PXFLAGS_ISPX;
+    Py_ORIG_TYPE(n) = NULL;
 
     if (is_varobj)
         assert(Py_SIZE(n) == nitems);
 }
 #endif
 
-/*
-__inline
-PyObject *
-_PyHeap_NewTuple(Context *c, Py_ssize_t nitems)
-{
-    return (PyObject *)VarObject_New(&PyTuple_Type, nitems, c);
-}
-
-__inline
-PyObject *
-_PyHeap_ResizeTuple(Context *c, PyObject *op, Py_ssize_t nitems)
-{
-    return (PyObject *)VarObject_Resize(op, nitems, c);
-}
-*/
-
 __inline
 int
 null_with_exc_or_non_none_return_type(PyObject *op, PyThreadState *tstate)
 
     goto done;
 
-/*
-free_wakeup:
-    CloseHandle(px->wakeup);
-*/
-
 free_finished:
     PxList_FreeListHead(px->finished);