prevent garbage leak

This commit is contained in:
Darren Ranalli 2006-12-30 00:22:49 +00:00
parent 93a5850c7b
commit a86451ad35

View File

@ -62,6 +62,12 @@ class EnforcesCalldowns:
if EnforcesCalldowns.notActive(): if EnforcesCalldowns.notActive():
return return
# protect against multiple calldowns via multiple inheritance
if hasattr(self, '_numInits'):
self._numInits += 1
else:
self._numInits = 1
# this map tracks how many times each func has been called # this map tracks how many times each func has been called
self._funcId2calls = {} self._funcId2calls = {}
# this map tracks the 'latch' values for each func; if the call count # this map tracks the 'latch' values for each func; if the call count
@ -105,12 +111,21 @@ class EnforcesCalldowns:
if EnforcesCalldowns.notActive(): if EnforcesCalldowns.notActive():
return return
# this must be called on destruction to prevent memory leaks # this must be called on destruction to prevent memory leaks
# protect against multiple calldowns via multiple inheritance
assert hasattr(self, '_numInits'), (
'too many calls to EnforcesCalldowns.EC_destroy, class=%s' % self.__class__.__name__)
if self._numInits == 1:
for name in self._obscuredMethodNames: for name in self._obscuredMethodNames:
# Functors need to be destroyed to prevent garbage leaks
getattr(self, name).destroy()
delattr(self, name) delattr(self, name)
del self._obscuredMethodNames del self._obscuredMethodNames
# this opens up more cans of worms. Let's keep it closed for the moment # this opens up more cans of worms. Let's keep it closed for the moment
#del self._funcId2calls #del self._funcId2calls
#del self._funcId2latch #del self._funcId2latch
del self._numInits
else:
self._numInits -= 1
def skipCalldown(self, method): def skipCalldown(self, method):
if EnforcesCalldowns.notActive(): if EnforcesCalldowns.notActive():
@ -164,15 +179,35 @@ if not EnforcesCalldowns.notActive():
class CalldownEnforceTestSubclass(CalldownEnforceTest): class CalldownEnforceTestSubclass(CalldownEnforceTest):
def testFunc(self): def testFunc(self):
CalldownEnforceTest.testFunc(self) CalldownEnforceTest.testFunc(self)
def destroy(self):
CalldownEnforceTest.EC_destroy(self)
class CalldownEnforceTestSubclassFail(CalldownEnforceTest): class CalldownEnforceTestSubclassFail(CalldownEnforceTest):
def testFunc(self): def testFunc(self):
pass pass
class CalldownEnforceTestSubclassSkip(CalldownEnforceTest): class CalldownEnforceTestSubclassSkip(CalldownEnforceTest):
def testFunc(self): def testFunc(self):
self.skipCalldown(CalldownEnforceTest.testFunc) self.skipCalldown(CalldownEnforceTest.testFunc)
class CalldownEnforceTestSubclass2(CalldownEnforceTest):
def testFunc(self):
CalldownEnforceTest.testFunc(self)
def destroy(self):
CalldownEnforceTest.EC_destroy(self)
class CalldownEnforceTestDiamond(CalldownEnforceTestSubclass,
CalldownEnforceTestSubclass2):
def __init__(self):
CalldownEnforceTestSubclass.__init__(self)
CalldownEnforceTestSubclass2.__init__(self)
def testFunc(self):
CalldownEnforceTestSubclass.testFunc(self)
CalldownEnforceTestSubclass2.testFunc(self)
def destroy(self):
CalldownEnforceTestSubclass.destroy(self)
CalldownEnforceTestSubclass2.destroy(self)
cets = CalldownEnforceTestSubclass() cets = CalldownEnforceTestSubclass()
cetsf = CalldownEnforceTestSubclassFail() cetsf = CalldownEnforceTestSubclassFail()
cetss = CalldownEnforceTestSubclassSkip() cetss = CalldownEnforceTestSubclassSkip()
cetd = CalldownEnforceTestDiamond()
raised = False raised = False
try: try:
cets.testFunc() cets.testFunc()
@ -194,12 +229,26 @@ if not EnforcesCalldowns.notActive():
raised = True raised = True
if raised: if raised:
raise "calldownEnforced.skipCalldown raised when it shouldn't" raise "calldownEnforced.skipCalldown raised when it shouldn't"
raised = False
cetd.testFunc()
msg = ''
try:
# make sure we're OK to call down to destroy multiple times
cetd.destroy()
except Exception, e:
msg = str(e)
raised = True
if raised:
raise "calldownEnforcedDiamond.destroy raised when it shouldn't\n%s" % msg
cetss.EC_destroy() cetss.EC_destroy()
cetsf.EC_destroy() cetsf.EC_destroy()
cets.EC_destroy() cets.EC_destroy()
del cetd
del cetss del cetss
del cetsf del cetsf
del cets del cets
del CalldownEnforceTestDiamond
del CalldownEnforceTestSubclass2
del CalldownEnforceTestSubclassSkip del CalldownEnforceTestSubclassSkip
del CalldownEnforceTestSubclassFail del CalldownEnforceTestSubclassFail
del CalldownEnforceTestSubclass del CalldownEnforceTestSubclass