CRDataCache.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. from direct.distributed.CachedDOData import CachedDOData
  2. class CRDataCache:
  3. # Stores cached data for DistributedObjects between instantiations on the client
  4. def __init__(self):
  5. self._doId2name2data = {}
  6. # maximum # of objects we will cache data for
  7. self._size = config.GetInt('crdatacache-size', 10)
  8. assert self._size > 0
  9. # used to preserve the cache size
  10. self._junkIndex = 0
  11. def destroy(self):
  12. del self._doId2name2data
  13. def setCachedData(self, doId, name, data):
  14. # stores a set of named data for a DistributedObject
  15. assert isinstance(data, CachedDOData)
  16. if len(self._doId2name2data) >= self._size:
  17. # cache is full, throw out a random doId's data
  18. if self._junkIndex >= len(self._doId2name2data):
  19. self._junkIndex = 0
  20. junkDoId = self._doId2name2data.keys()[self._junkIndex]
  21. self._junkIndex += 1
  22. for name in self._doId2name2data[junkDoId]:
  23. self._doId2name2data[junkDoId][name].flush()
  24. del self._doId2name2data[junkDoId]
  25. self._doId2name2data.setdefault(doId, {})
  26. cachedData = self._doId2name2data[doId].get(name)
  27. if cachedData:
  28. cachedData.flush()
  29. cachedData.destroy()
  30. self._doId2name2data[doId][name] = data
  31. def hasCachedData(self, doId):
  32. return doId in self._doId2name2data
  33. def popCachedData(self, doId):
  34. # retrieves all cached data for a DistributedObject and removes it from the cache
  35. data = self._doId2name2data[doId]
  36. del self._doId2name2data[doId]
  37. return data
  38. def flush(self):
  39. # get rid of all cached data
  40. for doId in self._doId2name2data:
  41. for name in self._doId2name2data[doId]:
  42. self._doId2name2data[doId][name].flush()
  43. self._doId2name2data = {}
  44. if __debug__:
  45. def _startMemLeakCheck(self):
  46. self._len = len(self._doId2name2data)
  47. def _stopMemLeakCheck(self):
  48. del self._len
  49. def _checkMemLeaks(self):
  50. assert self._len == len(self._doId2name2data)
  51. if __debug__:
  52. class TestCachedData(CachedDOData):
  53. def __init__(self):
  54. CachedDOData.__init__(self)
  55. self._destroyed = False
  56. self._flushed = False
  57. def destroy(self):
  58. CachedDOData.destroy(self)
  59. self._destroyed = True
  60. def flush(self):
  61. CachedDOData.flush(self)
  62. self._flushed = True
  63. dc = CRDataCache()
  64. dc._startMemLeakCheck()
  65. cd = CachedDOData()
  66. cd.foo = 34
  67. dc.setCachedData(1, 'testCachedData', cd)
  68. del cd
  69. cd = CachedDOData()
  70. cd.bar = 45
  71. dc.setCachedData(1, 'testCachedData2', cd)
  72. del cd
  73. assert dc.hasCachedData(1)
  74. assert dc.hasCachedData(1)
  75. assert not dc.hasCachedData(2)
  76. # data is dict of dataName->data
  77. data = dc.popCachedData(1)
  78. assert len(data) == 2
  79. assert 'testCachedData' in data
  80. assert 'testCachedData2' in data
  81. assert data['testCachedData'].foo == 34
  82. assert data['testCachedData2'].bar == 45
  83. for cd in data.itervalues():
  84. cd.flush()
  85. del data
  86. dc._checkMemLeaks()
  87. cd = CachedDOData()
  88. cd.bar = 1234
  89. dc.setCachedData(43, 'testCachedData2', cd)
  90. del cd
  91. assert dc.hasCachedData(43)
  92. dc.flush()
  93. dc._checkMemLeaks()
  94. dc._stopMemLeakCheck()
  95. dc.destroy()
  96. del dc