PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rlib/rweakref.py

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