[pypy-svn] r67451 - in pypy/branch/weakdict/pypy/rlib: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Sep 3 16:25:28 CEST 2009
Author: arigo
Date: Thu Sep 3 16:25:27 2009
New Revision: 67451
Added:
pypy/branch/weakdict/pypy/rlib/rweakref.py (contents, props changed)
pypy/branch/weakdict/pypy/rlib/rweakrefimpl.py (contents, props changed)
pypy/branch/weakdict/pypy/rlib/test/test_rweakref.py (contents, props changed)
Log:
Start an implementation of RWeakValueDictionary
using the controller mechanism for RTyping it.
Added: pypy/branch/weakdict/pypy/rlib/rweakref.py
==============================================================================
--- (empty file)
+++ pypy/branch/weakdict/pypy/rlib/rweakref.py Thu Sep 3 16:25:27 2009
@@ -0,0 +1,45 @@
+"""
+Weakref support in RPython. Supports ref() without callbacks,
+and a limited version of WeakValueDictionary. LLType only for now!
+"""
+
+import weakref
+from weakref import ref
+
+
+class RWeakValueDictionary(object):
+ """A limited dictionary containing weak values.
+ Only supports string keys.
+ """
+
+ def __init__(self, valueclass):
+ self._dict = weakref.WeakValueDictionary()
+ self._valueclass = valueclass
+
+ def get(self, key):
+ return self._dict.get(key, None)
+
+ def set(self, key, value):
+ if value is None:
+ self._dict.pop(key, None)
+ else:
+ assert isinstance(value, self._valueclass)
+ self._dict[key] = value
+
+
+# ____________________________________________________________
+
+from pypy.rpython import controllerentry
+
+ at staticmethod
+def _get_controller():
+ from pypy.rlib.rweakrefimpl import WeakDictController
+ return WeakDictController()
+
+class Entry(controllerentry.ControllerEntry):
+ _about_ = RWeakValueDictionary
+ _controller_ = _get_controller
+
+class Entry(controllerentry.ControllerEntryForPrebuilt):
+ _type_ = RWeakValueDictionary
+ _controller_ = _get_controller
Added: pypy/branch/weakdict/pypy/rlib/rweakrefimpl.py
==============================================================================
--- (empty file)
+++ pypy/branch/weakdict/pypy/rlib/rweakrefimpl.py Thu Sep 3 16:25:27 2009
@@ -0,0 +1,77 @@
+from pypy.rpython.lltypesystem import lltype, rstr, rclass, rdict
+from pypy.rpython.controllerentry import Controller
+from pypy.rpython.annlowlevel import llstr, cast_base_ptr_to_instance
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rweakref import RWeakValueDictionary
+
+
+class WeakDictController(Controller):
+ knowntype = RWeakValueDictionary
+
+ @specialize.arg(1)
+ def new(self, valueclass):
+ d = lltype.malloc(get_WEAKDICT(valueclass))
+ entries = lltype.malloc(WEAKDICTENTRYARRAY, DICT_INITSIZE)
+ for i in range(DICT_INITSIZE):
+ entries[i].key = pristine_marker
+ d.entries = entries
+ return d
+
+ def get_get(self, d):
+ return d.ll_get
+
+ def get_set(self, d):
+ return d.ll_set
+
+
+pristine_marker = lltype.malloc(rstr.STR, 0)
+DICT_INITSIZE = 8
+
+WEAKDICTENTRY = lltype.Struct("weakdictentry",
+ ("key", lltype.Ptr(rstr.STR)),
+ ("value", rclass.OBJECTPTR))
+
+def ll_valid(entries, i):
+ key = entries[i].key
+ return key != pristine_marker and bool(key)
+
+def ll_everused(entries, i):
+ key = entries[i].key
+ return key != pristine_marker
+
+entrymeths = {
+ 'valid': ll_valid,
+ 'everused': ll_everused,
+ }
+WEAKDICTENTRYARRAY = lltype.GcArray(WEAKDICTENTRY,
+ adtmeths=entrymeths,
+ hints={'weakarray': 'value'})
+
+def ll_get(d, key):
+ llkey = llstr(key)
+ i = rdict.ll_dict_lookup(d, llkey, llkey.gethash())
+ llvalue = d.entries[i].value
+ return cast_base_ptr_to_instance(d.valueclass, llvalue)
+
+def ll_set(d, key, value):
+ llkey = llstr(key)
+ llvalue = cast_instance_to_base_ptr(value)
+ i = rdict.ll_dict_lookup(d, llkey, llkey.gethash())
+ d.entries[i].key = llkey
+ d.entries[i].value = llvalue
+
+dictmeths = {
+ 'll_get': ll_get,
+ 'll_set': ll_set,
+ 'keyeq': None,
+ }
+
+ at specialize.memo()
+def get_WEAKDICT(valueclass):
+ adtmeths = dictmeths.copy()
+ adtmeths['valueclass'] = valueclass
+ WEAKDICT = lltype.GcStruct("weakdict",
+ ("entries", lltype.Ptr(WEAKDICTENTRYARRAY)),
+ adtmeths=adtmeths)
+ return WEAKDICT
Added: pypy/branch/weakdict/pypy/rlib/test/test_rweakref.py
==============================================================================
--- (empty file)
+++ pypy/branch/weakdict/pypy/rlib/test/test_rweakref.py Thu Sep 3 16:25:27 2009
@@ -0,0 +1,42 @@
+from pypy.rlib import rgc
+from pypy.rlib.rweakref import RWeakValueDictionary
+from pypy.rpython.test.test_llinterp import interpret
+
+class X(object):
+ pass
+
+
+def test_RWeakValueDictionary():
+ d = RWeakValueDictionary(X)
+ assert d.get("hello") is None
+ x1 = X(); x2 = X(); x3 = X()
+ d.set("abc", x1)
+ d.set("def", x2)
+ d.set("ghi", x3)
+ assert d.get("abc") is x1
+ assert d.get("def") is x2
+ assert d.get("ghi") is x3
+ assert d.get("hello") is None
+ x2 = None
+ rgc.collect(); rgc.collect()
+ assert d.get("abc") is x1
+ assert d.get("def") is None
+ assert d.get("ghi") is x3
+ assert d.get("hello") is None
+ d.set("abc", None)
+ assert d.get("abc") is None
+ assert d.get("def") is None
+ assert d.get("ghi") is x3
+ assert d.get("hello") is None
+ # resizing should also work
+ for i in range(100):
+ d.set(str(i), x1)
+ for i in range(100):
+ assert d.get(str(i)) is x1
+ assert d.get("abc") is None
+ assert d.get("def") is None
+ assert d.get("ghi") is x3
+ assert d.get("hello") is None
+
+#def test_rpython_RWeakValueDictionary():
+# interpret(test_RWeakValueDictionary, [])
More information about the Pypy-commit
mailing list