class A(object): def __init__(self): self.d = RWeakKeyDictionary(KX, A) def f(self, key): a = A() self.d.set(key, a) return a
def f(n): k = KX() v = VX() if n: d = empty else: d = RWeakKeyDictionary(KX, VX) d.set(k, v) return d.get(k) is v
def f(): d = prebuilt if d is None: d = RWeakKeyDictionary(KX, VX) k1, k3, v1, v2, v3 = g(d) rgc.collect() rgc.collect() assert d.get(k1) is v1 assert d.get(k3) is v3 assert d.get(k1) is not v2 assert d.get(k3) is not v2 assert d.length() == 2 d.set(k1, None) assert d.get(k1) is None assert d.get(k3) is v3 assert d.length() == 1 # resizing should also work lots_of_keys = [KX() for i in range(loop)] for k in lots_of_keys: d.set(k, v1) for k in lots_of_keys: assert d.get(k) is v1 assert d.get(k1) is None assert d.get(k3) is v3 assert d.length() == loop + 1 # a subclass ky = KY() vy = VY() d.set(ky, vy) assert d.get(ky) is vy assert d.length() == loop + 2 # deleting by storing Nones for k in lots_of_keys: d.set(k, None) for k in lots_of_keys: assert d.get(k) is None assert d.get(k1) is None assert d.get(k3) is v3 assert d.get(ky) is vy assert d.length() == 2
def f(): d = prebuilt if d is None: d = RWeakKeyDictionary(KX, VX) k1, k3, v1, v2, v3 = g(d) rgc.collect(); rgc.collect() assert d.get(k1) is v1 assert d.get(k3) is v3 assert d.get(k1) is not v2 assert d.get(k3) is not v2 assert d.length() == 2 d.set(k1, None) assert d.get(k1) is None assert d.get(k3) is v3 assert d.length() == 1 # resizing should also work lots_of_keys = [KX() for i in range(loop)] for k in lots_of_keys: d.set(k, v1) for k in lots_of_keys: assert d.get(k) is v1 assert d.get(k1) is None assert d.get(k3) is v3 assert d.length() == loop + 1 # a subclass ky = KY() vy = VY() d.set(ky, vy) assert d.get(ky) is vy assert d.length() == loop + 2 # deleting by storing Nones for k in lots_of_keys: d.set(k, None) for k in lots_of_keys: assert d.get(k) is None assert d.get(k1) is None assert d.get(k3) is v3 assert d.get(ky) is vy assert d.length() == 2
def add_me(): k = KX() v = VXDel() d = RWeakKeyDictionary(KX, VXDel) d.set(k, v) return d
def g(x): if x: d = RWeakKeyDictionary(KX, VX) else: d = RWeakKeyDictionary(KX, VY) d.set(KX(), VX())
class RefcountState: def __init__(self, space): self.space = space self.py_objects_w2r = {} # { w_obj -> raw PyObject } self.py_objects_r2w = {} # { addr of raw PyObject -> w_obj } self.lifeline_dict = RWeakKeyDictionary(W_Root, PyOLifeline) self.borrow_mapping = {None: {}} # { w_container -> { w_containee -> None } } # the None entry manages references borrowed during a call to # generic_cpy_call() # For tests self.non_heaptypes_w = [] def _cleanup_(self): assert self.borrow_mapping == {None: {}} self.py_objects_r2w.clear() # is not valid anymore after translation def init_r2w_from_w2r(self): """Rebuilds the dict py_objects_r2w on startup""" for w_obj, obj in self.py_objects_w2r.items(): ptr = rffi.cast(ADDR, obj) self.py_objects_r2w[ptr] = w_obj def print_refcounts(self): print "REFCOUNTS" for w_obj, obj in self.py_objects_w2r.items(): print "%r: %i" % (w_obj, obj.c_ob_refcnt) def get_from_lifeline(self, w_obj): lifeline = self.lifeline_dict.get(w_obj) if lifeline is not None: # make old PyObject ready for use in C code py_obj = lifeline.pyo assert py_obj.c_ob_refcnt == 0 return py_obj else: return lltype.nullptr(PyObject.TO) def set_lifeline(self, w_obj, py_obj): self.lifeline_dict.set(w_obj, PyOLifeline(self.space, py_obj)) def make_borrowed(self, w_container, w_borrowed): """ Create a borrowed reference, which will live as long as the container has a living reference (as a PyObject!) """ ref = make_ref(self.space, w_borrowed) obj_ptr = rffi.cast(ADDR, ref) borrowees = self.borrow_mapping.setdefault(w_container, {}) if w_borrowed in borrowees: Py_DecRef(self.space, w_borrowed) # cancel incref from make_ref() else: borrowees[w_borrowed] = None return ref def reset_borrowed_references(self): "Used in tests" for w_container, w_borrowed in self.borrow_mapping.items(): Py_DecRef(self.space, w_borrowed) self.borrow_mapping = {None: {}} def delete_borrower(self, w_obj): """ Called when a potential container for borrowed references has lost its last reference. Removes the borrowed references it contains. """ if w_obj in self.borrow_mapping: # move to lifeline __del__ for w_containee in self.borrow_mapping[w_obj]: self.forget_borrowee(w_containee) del self.borrow_mapping[w_obj] def swap_borrow_container(self, container): """switch the current default contained with the given one.""" if container is None: old_container = self.borrow_mapping[None] self.borrow_mapping[None] = {} return old_container else: old_container = self.borrow_mapping[None] self.borrow_mapping[None] = container for w_containee in old_container: self.forget_borrowee(w_containee) def forget_borrowee(self, w_obj): "De-register an object from the list of borrowed references" ref = self.py_objects_w2r.get(w_obj, lltype.nullptr(PyObject.TO)) if not ref: if DEBUG_REFCOUNT: print >>sys.stderr, "Borrowed object is already gone!" return Py_DecRef(self.space, ref)
class RefcountState: def __init__(self, space): self.space = space self.py_objects_w2r = {} # { w_obj -> raw PyObject } self.py_objects_r2w = {} # { addr of raw PyObject -> w_obj } self.lifeline_dict = RWeakKeyDictionary(W_Root, PyOLifeline) self.borrow_mapping = {None: {}} # { w_container -> { w_containee -> None } } # the None entry manages references borrowed during a call to # generic_cpy_call() # For tests self.non_heaptypes_w = [] def _cleanup_(self): assert self.borrow_mapping == {None: {}} self.py_objects_r2w.clear() # is not valid anymore after translation def init_r2w_from_w2r(self): """Rebuilds the dict py_objects_r2w on startup""" for w_obj, obj in self.py_objects_w2r.items(): ptr = rffi.cast(ADDR, obj) self.py_objects_r2w[ptr] = w_obj def print_refcounts(self): print "REFCOUNTS" for w_obj, obj in self.py_objects_w2r.items(): print "%r: %i" % (w_obj, obj.c_ob_refcnt) def get_from_lifeline(self, w_obj): lifeline = self.lifeline_dict.get(w_obj) if lifeline is not None: # make old PyObject ready for use in C code py_obj = lifeline.pyo assert py_obj.c_ob_refcnt == 0 return py_obj else: return lltype.nullptr(PyObject.TO) def set_lifeline(self, w_obj, py_obj): self.lifeline_dict.set(w_obj, PyOLifeline(self.space, py_obj)) def make_borrowed(self, w_container, w_borrowed): """ Create a borrowed reference, which will live as long as the container has a living reference (as a PyObject!) """ ref = make_ref(self.space, w_borrowed) obj_ptr = rffi.cast(ADDR, ref) borrowees = self.borrow_mapping.setdefault(w_container, {}) if w_borrowed in borrowees: Py_DecRef(self.space, w_borrowed) # cancel incref from make_ref() else: borrowees[w_borrowed] = None return ref def reset_borrowed_references(self): "Used in tests" for w_container, w_borrowed in self.borrow_mapping.items(): Py_DecRef(self.space, w_borrowed) self.borrow_mapping = {None: {}} def delete_borrower(self, w_obj): """ Called when a potential container for borrowed references has lost its last reference. Removes the borrowed references it contains. """ if w_obj in self.borrow_mapping: # move to lifeline __del__ for w_containee in self.borrow_mapping[w_obj]: self.forget_borrowee(w_containee) del self.borrow_mapping[w_obj] def swap_borrow_container(self, container): """switch the current default contained with the given one.""" if container is None: old_container = self.borrow_mapping[None] self.borrow_mapping[None] = {} return old_container else: old_container = self.borrow_mapping[None] self.borrow_mapping[None] = container for w_containee in old_container: self.forget_borrowee(w_containee) def forget_borrowee(self, w_obj): "De-register an object from the list of borrowed references" ref = self.py_objects_w2r.get(w_obj, lltype.nullptr(PyObject.TO)) if not ref: if DEBUG_REFCOUNT: print >> sys.stderr, "Borrowed object is already gone!" return Py_DecRef(self.space, ref)