Rev 130: the collection now manages a weakref list of proxy instances. in http://bazaar.launchpad.net/~jameinel/meliae/mem-object-collection
John Arbash Meinel
john at arbash-meinel.com
Mon Dec 28 03:30:15 GMT 2009
At http://bazaar.launchpad.net/~jameinel/meliae/mem-object-collection
------------------------------------------------------------
revno: 130
revision-id: john at arbash-meinel.com-20091228033001-vwjof7itsddctrua
parent: john at arbash-meinel.com-20091228005448-hm6ll74g7cw7slw2
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: mem-object-collection
timestamp: Sun 2009-12-27 21:30:01 -0600
message:
the collection now manages a weakref list of proxy instances.
This way, when an item is deleted, we can invalidate its proxy, even if
we can't get rid of the proxy itself.
An alternative would be to transfer the memory control over to the proxy,
assuming we always have one-and-only-one proxy.
-------------- next part --------------
=== modified file 'meliae/_loader.pyx'
--- a/meliae/_loader.pyx 2009-12-28 00:54:48 +0000
+++ b/meliae/_loader.pyx 2009-12-28 03:30:01 +0000
@@ -37,6 +37,8 @@
# void fprintf(void *, char *, ...)
# void *stderr
+import weakref
+
ctypedef struct RefList:
long size
@@ -166,40 +168,37 @@
self.collection = collection
self._obj = NULL
- cdef _MemObject *_get_obj(self) except NULL:
+ cdef _MemObject *_ensure_obj(self) except NULL:
if self._obj is NULL:
raise RuntimeError('_MemObjectProxy was deleted underneath it.')
return self._obj
+ def is_valid(self):
+ if self._obj is NULL:
+ return False
+ return True
+
property type_str:
"""The type of this object."""
def __get__(self):
- cdef _MemObject *slot
-
- slot = self._get_obj()
- return <object>(slot.type_str)
+ self._ensure_obj()
+ return <object>(self._obj.type_str)
property size:
"""The number of bytes allocated for this object."""
def __get__(self):
- cdef _MemObject *slot
-
- slot = self._get_obj()
- return slot.size
+ self._ensure_obj()
+ return self._obj.size
def __set__(self, value):
- cdef _MemObject *slot
-
- slot = self._get_obj()
- slot.size = value
+ self._ensure_obj()
+ self._obj.size = value
def __len__(self):
- cdef _MemObject *slot
-
- slot = self._get_obj()
- if slot.ref_list == NULL:
+ self._ensure_obj()
+ if self._obj.ref_list == NULL:
return 0
- return slot.ref_list.size
+ return self._obj.ref_list.size
# def __getitem__(self, offset):
# cdef _MemObject *slot
@@ -223,12 +222,14 @@
cdef readonly int _table_mask # N slots = table_mask + 1
cdef readonly int _active # How many slots have real data
cdef readonly int _filled # How many slots have real or dummy
- cdef _MemObject** _table # _MemObjects are stored inline
+ cdef _MemObject** _table # _MemObjects are stored inline
+ cdef public object _proxies # _MemObjectProxy instances
def __init__(self):
self._table_mask = 1024 - 1
self._table = <_MemObject**>PyMem_Malloc(sizeof(_MemObject*)*1024)
memset(self._table, 0, sizeof(_MemObject*)*1024)
+ self._proxies = weakref.WeakValueDictionary()
cdef _MemObject** _lookup(self, address) except NULL:
cdef long the_hash
@@ -320,8 +321,12 @@
if slot[0] == NULL or slot[0] == _dummy:
raise KeyError('address %s not present' % (at,))
if proxy is None:
- proxy = _MemObjectProxy(address, self)
- proxy._obj = slot[0]
+ if address in self._proxies:
+ proxy = self._proxies[address]
+ else:
+ proxy = _MemObjectProxy(address, self)
+ proxy._obj = slot[0]
+ self._proxies[address] = proxy
return proxy
def __delitem__(self, at):
@@ -336,6 +341,9 @@
slot = self._lookup(address)
if slot[0] == NULL or slot[0] == _dummy:
raise KeyError('address %s not present' % (at,))
+ proxy = self._proxies.get(address, None)
+ if proxy is not None:
+ proxy._obj = NULL
self._clear_slot(slot)
slot[0] = _dummy
# TODO: Shrink
=== modified file 'meliae/tests/test__loader.py'
--- a/meliae/tests/test__loader.py 2009-12-28 00:54:48 +0000
+++ b/meliae/tests/test__loader.py 2009-12-28 03:30:01 +0000
@@ -223,3 +223,11 @@
self.assertEqual(1024, mop.size)
self.assertEqual(1024, self.moc[0].size)
self.assertEqual(0, len(mop))
+
+ def test_deleted_proxy(self):
+ mop = self.moc[0]
+ del self.moc[0]
+ self.assertFalse(mop.is_valid())
+ self.assertRaises(RuntimeError, lambda: mop.type_str)
+ self.assertRaises(RuntimeError, lambda: mop.size)
+ self.assertRaises(RuntimeError, len, mop)
More information about the bazaar-commits
mailing list