PageRenderTime 28ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rlib/rweakref.py

https://bitbucket.org/squeaky/pypy
Python | 208 lines | 184 code | 13 blank | 11 comment | 4 complexity | e10aaf8967fd361bd8710ae8f8c5bfca MD5 | raw file
Possible License(s): Apache-2.0
  1. """
  2. Weakref support in RPython. Basic regular weakrefs without callbacks
  3. are supported. This file contains the following additions:
  4. a form of WeakKeyDictionary, and a limited version of WeakValueDictionary.
  5. LLType only for now!
  6. """
  7. import weakref
  8. ref = weakref.ref # basic regular weakrefs are supported in RPython
  9. def has_weakref_support():
  10. return True # returns False if --no-translation-rweakref
  11. class Dummy:
  12. pass
  13. dead_ref = weakref.ref(Dummy())
  14. for i in range(5):
  15. if dead_ref() is not None:
  16. import gc; gc.collect()
  17. assert dead_ref() is None # a known-to-be-dead weakref object
  18. class RWeakValueDictionary(object):
  19. """A dictionary containing weak values."""
  20. def __init__(self, keyclass, valueclass):
  21. self._dict = weakref.WeakValueDictionary()
  22. self._keyclass = keyclass
  23. self._valueclass = valueclass
  24. def get(self, key):
  25. assert isinstance(key, self._keyclass)
  26. return self._dict.get(key, None)
  27. def set(self, key, value):
  28. assert isinstance(key, self._keyclass)
  29. if value is None:
  30. self._dict.pop(key, None)
  31. else:
  32. assert isinstance(value, self._valueclass)
  33. self._dict[key] = value
  34. class RWeakKeyDictionary(object):
  35. """A dictionary containing weak keys.
  36. Keys and values must be instances.
  37. Prebuilt RWeakKeyDictionaries must be empty.
  38. """
  39. def __init__(self, keyclass, valueclass):
  40. self._dict = weakref.WeakKeyDictionary()
  41. self._keyclass = keyclass
  42. self._valueclass = valueclass
  43. def get(self, key):
  44. """Get the value associated to 'key', or None by default."""
  45. assert isinstance(key, self._keyclass)
  46. return self._dict.get(key, None)
  47. def set(self, key, value):
  48. """Set the key/value pair (or delete it if value is None)."""
  49. assert isinstance(key, self._keyclass)
  50. if value is None:
  51. self._dict.pop(key, None)
  52. else:
  53. assert isinstance(value, self._valueclass)
  54. self._dict[key] = value
  55. def length(self):
  56. """Mostly for debugging. Slow, don't use in real code."""
  57. return len(self._dict)
  58. # ____________________________________________________________
  59. from rpython.rtyper import extregistry
  60. from rpython.annotator import model as annmodel
  61. from rpython.tool.pairtype import pairtype
  62. class Entry(extregistry.ExtRegistryEntry):
  63. _about_ = has_weakref_support
  64. def compute_result_annotation(self):
  65. translator = self.bookkeeper.annotator.translator
  66. res = translator.config.translation.rweakref
  67. return self.bookkeeper.immutablevalue(res)
  68. def specialize_call(self, hop):
  69. from rpython.rtyper.lltypesystem import lltype
  70. hop.exception_cannot_occur()
  71. return hop.inputconst(lltype.Bool, hop.s_result.const)
  72. class SomeWeakValueDict(annmodel.SomeObject):
  73. knowntype = RWeakValueDictionary
  74. def __init__(self, s_key, valueclassdef):
  75. self.s_key = s_key
  76. self.valueclassdef = valueclassdef
  77. def rtyper_makerepr(self, rtyper):
  78. from rpython.rlib import _rweakvaldict
  79. return _rweakvaldict.WeakValueDictRepr(rtyper,
  80. rtyper.getrepr(self.s_key))
  81. def rtyper_makekey_ex(self, rtyper):
  82. return self.__class__,
  83. def method_get(self, s_key):
  84. return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
  85. def method_set(self, s_key, s_value):
  86. s_oldvalue = self.method_get(s_key)
  87. assert s_oldvalue.contains(s_value)
  88. class __extend__(pairtype(SomeWeakValueDict, SomeWeakValueDict)):
  89. def union((s_wvd1, s_wvd2)):
  90. if s_wvd1.valueclassdef is not s_wvd2.valueclassdef:
  91. return annmodel.SomeObject() # not the same class! complain...
  92. s_key = annmodel.unionof(s_wvd1.s_key, s_wvd2.s_key)
  93. return SomeWeakValueDict(s_key, s_wvd1.valueclassdef)
  94. class Entry(extregistry.ExtRegistryEntry):
  95. _about_ = RWeakValueDictionary
  96. def compute_result_annotation(self, s_keyclass, s_valueclass):
  97. assert s_keyclass.is_constant()
  98. s_key = self.bookkeeper.immutablevalue(s_keyclass.const())
  99. return SomeWeakValueDict(
  100. s_key,
  101. _getclassdef(s_valueclass))
  102. def specialize_call(self, hop):
  103. from rpython.rlib import _rweakvaldict
  104. return _rweakvaldict.specialize_make_weakdict(hop)
  105. class Entry(extregistry.ExtRegistryEntry):
  106. _type_ = RWeakValueDictionary
  107. def compute_annotation(self):
  108. bk = self.bookkeeper
  109. x = self.instance
  110. return SomeWeakValueDict(
  111. bk.immutablevalue(x._keyclass()),
  112. bk.getuniqueclassdef(x._valueclass))
  113. def _getclassdef(s_instance):
  114. assert isinstance(s_instance, annmodel.SomePBC)
  115. assert s_instance.is_constant()
  116. [desc] = s_instance.descriptions
  117. return desc.getuniqueclassdef()
  118. # ____________________________________________________________
  119. class SomeWeakKeyDict(annmodel.SomeObject):
  120. knowntype = RWeakKeyDictionary
  121. def __init__(self, keyclassdef, valueclassdef):
  122. self.keyclassdef = keyclassdef
  123. self.valueclassdef = valueclassdef
  124. def rtyper_makerepr(self, rtyper):
  125. from rpython.rlib import _rweakkeydict
  126. return _rweakkeydict.WeakKeyDictRepr(rtyper)
  127. def rtyper_makekey_ex(self, rtyper):
  128. return self.__class__,
  129. def method_get(self, s_key):
  130. assert isinstance(s_key, annmodel.SomeInstance)
  131. assert s_key.classdef.issubclass(self.keyclassdef)
  132. return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
  133. def method_set(self, s_key, s_value):
  134. s_oldvalue = self.method_get(s_key)
  135. assert s_oldvalue.contains(s_value)
  136. def method_length(self):
  137. return annmodel.SomeInteger(nonneg=True)
  138. class __extend__(pairtype(SomeWeakKeyDict, SomeWeakKeyDict)):
  139. def union((s_wkd1, s_wkd2)):
  140. if s_wkd1.keyclassdef is not s_wkd2.keyclassdef:
  141. return SomeObject() # not the same key class! complain...
  142. if s_wkd1.valueclassdef is not s_wkd2.valueclassdef:
  143. return SomeObject() # not the same value class! complain...
  144. return SomeWeakKeyDict(s_wkd1.keyclassdef, s_wkd1.valueclassdef)
  145. class Entry(extregistry.ExtRegistryEntry):
  146. _about_ = RWeakKeyDictionary
  147. def compute_result_annotation(self, s_keyclass, s_valueclass):
  148. return SomeWeakKeyDict(_getclassdef(s_keyclass),
  149. _getclassdef(s_valueclass))
  150. def specialize_call(self, hop):
  151. from rpython.rlib import _rweakkeydict
  152. return _rweakkeydict.specialize_make_weakdict(hop)
  153. class Entry(extregistry.ExtRegistryEntry):
  154. _type_ = RWeakKeyDictionary
  155. def compute_annotation(self):
  156. bk = self.bookkeeper
  157. x = self.instance
  158. return SomeWeakKeyDict(bk.getuniqueclassdef(x._keyclass),
  159. bk.getuniqueclassdef(x._valueclass))