| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- from direct.distributed.CachedDOData import CachedDOData
- from panda3d.core import ConfigVariableInt
- __all__ = ["CRDataCache"]
- class CRDataCache:
- # Stores cached data for DistributedObjects between instantiations on the client
- def __init__(self):
- self._doId2name2data = {}
- # maximum # of objects we will cache data for
- self._size = ConfigVariableInt('crdatacache-size', 10).getValue()
- assert self._size > 0
- # used to preserve the cache size
- self._junkIndex = 0
- def destroy(self):
- del self._doId2name2data
- def setCachedData(self, doId, name, data):
- # stores a set of named data for a DistributedObject
- assert isinstance(data, CachedDOData)
- if len(self._doId2name2data) >= self._size:
- # cache is full, throw out a random doId's data
- if self._junkIndex >= len(self._doId2name2data):
- self._junkIndex = 0
- junkDoId = list(self._doId2name2data.keys())[self._junkIndex]
- self._junkIndex += 1
- for name in self._doId2name2data[junkDoId]:
- self._doId2name2data[junkDoId][name].flush()
- del self._doId2name2data[junkDoId]
- self._doId2name2data.setdefault(doId, {})
- cachedData = self._doId2name2data[doId].get(name)
- if cachedData:
- cachedData.flush()
- cachedData.destroy()
- self._doId2name2data[doId][name] = data
- def hasCachedData(self, doId):
- return doId in self._doId2name2data
- def popCachedData(self, doId):
- # retrieves all cached data for a DistributedObject and removes it from the cache
- data = self._doId2name2data[doId]
- del self._doId2name2data[doId]
- return data
- def flush(self):
- # get rid of all cached data
- for doId in self._doId2name2data:
- for name in self._doId2name2data[doId]:
- self._doId2name2data[doId][name].flush()
- self._doId2name2data = {}
- if __debug__:
- def _startMemLeakCheck(self):
- self._len = len(self._doId2name2data)
- def _stopMemLeakCheck(self):
- del self._len
- def _checkMemLeaks(self):
- assert self._len == len(self._doId2name2data)
- if __debug__:
- class TestCachedData(CachedDOData):
- def __init__(self):
- CachedDOData.__init__(self)
- self._destroyed = False
- self._flushed = False
- def destroy(self):
- CachedDOData.destroy(self)
- self._destroyed = True
- def flush(self):
- CachedDOData.flush(self)
- self._flushed = True
- dc = CRDataCache()
- dc._startMemLeakCheck()
- cd = CachedDOData()
- cd.foo = 34
- dc.setCachedData(1, 'testCachedData', cd)
- del cd
- cd = CachedDOData()
- cd.bar = 45
- dc.setCachedData(1, 'testCachedData2', cd)
- del cd
- assert dc.hasCachedData(1)
- assert dc.hasCachedData(1)
- assert not dc.hasCachedData(2)
- # data is dict of dataName->data
- data = dc.popCachedData(1)
- assert len(data) == 2
- assert 'testCachedData' in data
- assert 'testCachedData2' in data
- assert data['testCachedData'].foo == 34
- assert data['testCachedData2'].bar == 45
- for cd in data.values():
- cd.flush()
- del data
- dc._checkMemLeaks()
- cd = CachedDOData()
- cd.bar = 1234
- dc.setCachedData(43, 'testCachedData2', cd)
- del cd
- assert dc.hasCachedData(43)
- dc.flush()
- dc._checkMemLeaks()
- dc._stopMemLeakCheck()
- dc.destroy()
- del dc
|