Author: Armin Rigo <[email protected]>
Branch: finalizer
Changeset: r1466:d5a95166f741
Date: 2014-10-06 18:23 +0200
http://bitbucket.org/pypy/stmgc/changeset/d5a95166f741/
Log: Write down some rules, and figured out that there is a problem with
light finalizers too
diff --git a/c7/stm/finalizer.c b/c7/stm/finalizer.c
--- a/c7/stm/finalizer.c
+++ b/c7/stm/finalizer.c
@@ -1,6 +1,7 @@
void (*stmcb_light_finalizer)(object_t *);
+void (*stmcb_finalizer)(object_t *);
void stm_enable_light_finalizer(object_t *obj)
{
@@ -10,6 +11,11 @@
LIST_APPEND(STM_PSEGMENT->old_objects_with_light_finalizers, obj);
}
+object_t *stm_allocate_with_finalizer(ssize_t size_rounded_up)
+{
+ abort(); // NOT IMPLEMENTED
+}
+
static void deal_with_young_objects_with_finalizers(void)
{
/* for light finalizers */
@@ -47,7 +53,7 @@
object_t* obj = (object_t *)list_item(lst, i);
if (!mark_visited_test(obj)) {
/* not marked: object dies */
- /* we're calling the light finalizer is a random thread,
+ /* we're calling the light finalizer in a random thread,
but it should work, because it was dead already at the
start of that thread's transaction, so any thread should
see the same, old content */
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -511,6 +511,18 @@
void (*stmcb_light_finalizer)(object_t *);
void stm_enable_light_finalizer(object_t *);
+/* Support for regular finalizers. Unreachable objects with
+ finalizers are kept alive, as well as everything they point to, and
+ stmcb_finalizer() is called after the major GC. If there are
+ several objects with finalizers that reference each other in a
+ well-defined order (i.e. there are no cycles), then they are
+ finalized in order from outermost to innermost (i.e. starting with
+ the ones that are unreachable even from others). The finalizer is
+ called in a random thread, except for objects that have been
+ created by the current transaction in a thread; in that case, only
+ that thread can call the finalizer. */
+void (*stmcb_finalizer)(object_t *);
+object_t *stm_allocate_with_finalizer(ssize_t size_rounded_up);
/* ==================== END ==================== */
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -31,6 +31,7 @@
/*void stm_write(object_t *obj); use _checked_stm_write() instead */
object_t *stm_allocate(ssize_t size_rounded_up);
object_t *stm_allocate_weakref(ssize_t size_rounded_up);
+object_t *stm_allocate_with_finalizer(ssize_t size_rounded_up);
object_t *_stm_allocate_old(ssize_t size_rounded_up);
/*void stm_write_card(); use _checked_stm_write_card() instead */
diff --git a/c7/test/test_finalizer.py b/c7/test/test_finalizer.py
--- a/c7/test/test_finalizer.py
+++ b/c7/test/test_finalizer.py
@@ -73,3 +73,32 @@
stm_major_collect()
self.commit_transaction()
self.expect_finalized([])
+
+
+class TestRegularFinalizer(BaseTest):
+
+ def setup_method(self, meth):
+ BaseTest.setup_method(self, meth)
+ #
+ @ffi.callback("void(object_t *)")
+ def finalizer(obj):
+ self.finalizers_called.append(obj)
+ self.finalizers_called = []
+ lib.stmcb_finalizer = finalizer
+ self._finalizer_keepalive = finalizer
+
+ def expect_finalized(self, objs):
+ assert self.finalizers_called == objs
+ self.finalizers_called = []
+
+ def test_no_finalizer(self):
+ self.start_transaction()
+ lp1 = stm_allocate(48)
+ stm_major_collect()
+ self.expect_finalized([])
+
+ def test_no_finalizer_in_minor_collection(self):
+ self.start_transaction()
+ lp1 = stm_allocate_with_finalizer(48)
+ stm_minor_collect()
+ self.expect_finalized([])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit