[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