colls.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import weakref
  2. from threading import Lock
  3. class WeakValueDict(object):
  4. """a light-weight version of weakref.WeakValueDictionary"""
  5. __slots__ = ("_dict",)
  6. def __init__(self):
  7. self._dict = {}
  8. def __repr__(self):
  9. return repr(self._dict)
  10. def __iter__(self):
  11. return self.iterkeys()
  12. def __len__(self):
  13. return len(self._dict)
  14. def __contains__(self, key):
  15. try:
  16. self[key]
  17. except KeyError:
  18. return False
  19. else:
  20. return True
  21. def get(self, key, default = None):
  22. try:
  23. return self[key]
  24. except KeyError:
  25. return default
  26. def __getitem__(self, key):
  27. obj = self._dict[key]()
  28. if obj is None:
  29. raise KeyError(key)
  30. return obj
  31. def __setitem__(self, key, value):
  32. def remover(wr, _dict = self._dict, key = key):
  33. _dict.pop(key, None)
  34. self._dict[key] = weakref.ref(value, remover)
  35. def __delitem__(self, key):
  36. del self._dict[key]
  37. def iterkeys(self):
  38. return self._dict.iterkeys()
  39. def keys(self):
  40. return self._dict.keys()
  41. def itervalues(self):
  42. for k in self:
  43. yield self[k]
  44. def values(self):
  45. return list(self.itervalues())
  46. def iteritems(self):
  47. for k in self:
  48. yield k, self[k]
  49. def items(self):
  50. return list(self.iteritems())
  51. def clear(self):
  52. self._dict.clear()
  53. class RefCountingColl(object):
  54. """a set-like object that implements refcounting on its contained objects"""
  55. __slots__ = ("_lock", "_dict")
  56. def __init__(self):
  57. self._lock = Lock()
  58. self._dict = {}
  59. def __repr__(self):
  60. return repr(self._dict)
  61. def add(self, obj):
  62. self._lock.acquire()
  63. try:
  64. key = id(obj)
  65. slot = self._dict.get(key, None)
  66. if slot is None:
  67. slot = [obj, 0]
  68. else:
  69. slot[1] += 1
  70. self._dict[key] = slot
  71. finally:
  72. self._lock.release()
  73. def clear(self):
  74. self._lock.acquire()
  75. try:
  76. self._dict.clear()
  77. finally:
  78. self._lock.release()
  79. def decref(self, key):
  80. self._lock.acquire()
  81. try:
  82. slot = self._dict[key]
  83. if slot[1] <= 1:
  84. del self._dict[key]
  85. else:
  86. slot[1] -= 1
  87. self._dict[key] = slot
  88. finally:
  89. self._lock.release()
  90. def __getitem__(self, key):
  91. self._lock.acquire()
  92. try:
  93. return self._dict[key][0]
  94. finally:
  95. self._lock.release()