assert when subclassing rules are not followed

This commit is contained in:
Josh Wilson 2007-06-10 08:35:09 +00:00
parent 5e3a807168
commit 386bf49c0d

View File

@ -3,13 +3,14 @@ class ResourceCounter(object):
"""
This class is an attempt to combine the RAIA idiom with reference
counting semantics in order to model shared resources. RAIA stands
for "Resource Allocation Is Acquisiton" (see 'Effective C++' for a
more detailed explanation)
for "Resource Allocation Is Acquisition" (see 'Effective C++' for a
more in-depth explanation)
When a resource is needed, create an appropriate ResourceCounter
object. If the resource is already available (meaning another
ResourceCounter object of the same type already exists), no action
is taken. The resource will remain valid until all matching
is taken. Otherwise, acquire() is invoked, and the resource is
allocated. The resource will remain valid until all matching
ResourceCounter objects have been deleted. When no objects of
a particular ResourceCounter type exist, the release() function for
that type is invoked and the managed resource is cleaned up.
@ -27,10 +28,11 @@ class ResourceCounter(object):
Until we figure out a way to wrangle a bit more functionality out
of Python, you MUST NOT define acquire() and release() again in
any subclasses of your ResourceCounter subclass in an attempt
to manage another resource. If you have more than one resource,
to manage another resource. In debug mode, this will raise a
runtime assertion. If you have more than one resource, you should
subclass ResourceCounter again. See the example code at the
bottom of this file to see how to manage more than one resource with
a single instance of an object (Useful for dependent resources).
bottom of this file to see how to manage more than one resource
with a single instance of an object (Useful for dependent resources).
"""
@classmethod
@ -46,18 +48,22 @@ class ResourceCounter(object):
@classmethod
def decrementCounter(cls):
cls.RESOURCE_COUNTER -= 1
if cls.RESOURCE_COUNTER == 0:
if cls.RESOURCE_COUNTER < 1:
cls.release()
@classmethod
def acquire(cls):
pass
cls.RESOURCE_COUNTER -= 1
assert cls.__mro__[1] == ResourceCounter, \
(lambda: \
'acquire() should only be defined in ResourceCounter\'s immediate subclass: %s' \
% cls.__mro__[list(cls.__mro__).index(ResourceCounter) - 1].__name__)()
cls.RESOURCE_COUNTER += 1
@classmethod
def release(cls, *args, **kwargs):
pass
def __init__(self):
self.incrementCounter()
@ -73,19 +79,20 @@ if __debug__ and __name__ == '__main__':
"""
@classmethod
def acquire(cls):
ResourceCounter.acquire()
print '-- Acquiring Mouse'
super(MouseResource, cls).acquire()
print '-- Acquire Mouse'
@classmethod
def release(cls):
ResourceCounter.release()
print '-- Releasing Mouse'
print '-- Release Mouse'
super(MouseResource, cls).release()
def __init__(self):
ResourceCounter.__init__(self)
super(MouseResource, self).__init__()
def __del__(self):
ResourceCounter.__del__(self)
super(MouseResource, self).__del__()
class CursorResource(ResourceCounter):
"""
@ -93,26 +100,38 @@ if __debug__ and __name__ == '__main__':
resource. Notice how this class also inherits from
ResourceCounter. Instead of subclassing MouseCounter,
we will just acquire it in our __init__() and release
it in our
it in our __del__().
"""
@classmethod
def acquire(cls):
print '-- Acquiring Cursor'
ResourceCounter.acquire()
super(CursorResource, cls).acquire()
print '-- Acquire Cursor'
@classmethod
def release(cls):
print '-- Releasing Cursor'
ResourceCounter.release()
print '-- Release Cursor'
super(CursorResource, cls).release()
def __init__(self):
self.__mouseResource = MouseResource()
ResourceCounter.__init__(self)
super(CursorResource, self).__init__()
def __del__(self):
ResourceCounter.__del__(self)
super(CursorResource, self).__del__()
del self.__mouseResource
class InvalidResource(MouseResource):
@classmethod
def acquire(cls):
super(InvalidResource, cls).acquire()
print '-- Acquire Invalid'
@classmethod
def release(cls):
print '-- Release Invalid'
super(InvalidResource, cls).release()
print '\nAllocate Mouse'
m = MouseResource()
print 'Free up Mouse'
@ -154,13 +173,21 @@ if __debug__ and __name__ == '__main__':
del m
print 'Free up Cursor'
del c
# example of an invalid subclass
try:
print '\nAllocate Invalid'
i = InvalidResource()
print 'Free up Invalid'
except AssertionError,e:
print e
def demoFunc():
print '\nAllocate Cursor within function'
c = CursorResource()
print 'Cursor will be freed on function exit'
demoFunc()