PageRenderTime 25ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rlib/rweaklist.py

https://bitbucket.org/pypy/pypy/
Python | 57 lines | 34 code | 9 blank | 14 comment | 6 complexity | 50e9a2c5f65bc4276348b29d8fd30e9c MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import weakref
  2. from rpython.rlib.rweakref import dead_ref
  3. INITIAL_SIZE = 4
  4. class RWeakListMixin(object):
  5. """A mixin base class. A collection that weakly maps indexes to objects.
  6. After an object goes away, its index is marked free and will be reused
  7. by some following add_handle() call. So add_handle() might not append
  8. the object at the end of the list, but can put it anywhere.
  9. See also rpython.rlib.rshrinklist.
  10. """
  11. _mixin_ = True
  12. def initialize(self):
  13. self.handles = [dead_ref] * INITIAL_SIZE
  14. self.free_list = range(INITIAL_SIZE)
  15. def get_all_handles(self):
  16. return self.handles
  17. def reserve_next_handle_index(self):
  18. # (this algorithm should be amortized constant-time)
  19. # get the next 'free_list' entry, if any
  20. free_list = self.free_list
  21. try:
  22. return free_list.pop()
  23. except IndexError:
  24. pass
  25. # slow path: collect all now-free handles in 'free_list'
  26. handles = self.handles
  27. for i in range(len(handles)):
  28. if handles[i]() is None:
  29. free_list.append(i)
  30. # double the size of the self.handles list, but don't do that
  31. # if there are more than 66% of handles free already
  32. if len(free_list) * 3 < len(handles) * 2:
  33. free_list.extend(range(len(handles), len(handles) * 2))
  34. # don't use '+=' on 'self.handles'
  35. self.handles = handles = handles + [dead_ref] * len(handles)
  36. #
  37. return free_list.pop()
  38. def add_handle(self, content):
  39. index = self.reserve_next_handle_index()
  40. self.store_handle(index, content)
  41. return index
  42. def store_handle(self, index, content):
  43. self.handles[index] = weakref.ref(content)
  44. def fetch_handle(self, index):
  45. if 0 <= index < len(self.handles):
  46. return self.handles[index]()
  47. return None