mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 19:08:55 -04:00
assert when subclassing rules are not followed
This commit is contained in:
parent
5e3a807168
commit
386bf49c0d
@ -3,13 +3,14 @@ class ResourceCounter(object):
|
|||||||
"""
|
"""
|
||||||
This class is an attempt to combine the RAIA idiom with reference
|
This class is an attempt to combine the RAIA idiom with reference
|
||||||
counting semantics in order to model shared resources. RAIA stands
|
counting semantics in order to model shared resources. RAIA stands
|
||||||
for "Resource Allocation Is Acquisiton" (see 'Effective C++' for a
|
for "Resource Allocation Is Acquisition" (see 'Effective C++' for a
|
||||||
more detailed explanation)
|
more in-depth explanation)
|
||||||
|
|
||||||
When a resource is needed, create an appropriate ResourceCounter
|
When a resource is needed, create an appropriate ResourceCounter
|
||||||
object. If the resource is already available (meaning another
|
object. If the resource is already available (meaning another
|
||||||
ResourceCounter object of the same type already exists), no action
|
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
|
ResourceCounter objects have been deleted. When no objects of
|
||||||
a particular ResourceCounter type exist, the release() function for
|
a particular ResourceCounter type exist, the release() function for
|
||||||
that type is invoked and the managed resource is cleaned up.
|
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
|
Until we figure out a way to wrangle a bit more functionality out
|
||||||
of Python, you MUST NOT define acquire() and release() again in
|
of Python, you MUST NOT define acquire() and release() again in
|
||||||
any subclasses of your ResourceCounter subclass in an attempt
|
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
|
subclass ResourceCounter again. See the example code at the
|
||||||
bottom of this file to see how to manage more than one resource with
|
bottom of this file to see how to manage more than one resource
|
||||||
a single instance of an object (Useful for dependent resources).
|
with a single instance of an object (Useful for dependent resources).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -46,18 +48,22 @@ class ResourceCounter(object):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def decrementCounter(cls):
|
def decrementCounter(cls):
|
||||||
cls.RESOURCE_COUNTER -= 1
|
cls.RESOURCE_COUNTER -= 1
|
||||||
|
if cls.RESOURCE_COUNTER < 1:
|
||||||
if cls.RESOURCE_COUNTER == 0:
|
|
||||||
cls.release()
|
cls.release()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def acquire(cls):
|
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
|
@classmethod
|
||||||
def release(cls, *args, **kwargs):
|
def release(cls, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.incrementCounter()
|
self.incrementCounter()
|
||||||
@ -73,19 +79,20 @@ if __debug__ and __name__ == '__main__':
|
|||||||
"""
|
"""
|
||||||
@classmethod
|
@classmethod
|
||||||
def acquire(cls):
|
def acquire(cls):
|
||||||
ResourceCounter.acquire()
|
super(MouseResource, cls).acquire()
|
||||||
print '-- Acquiring Mouse'
|
print '-- Acquire Mouse'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def release(cls):
|
def release(cls):
|
||||||
ResourceCounter.release()
|
print '-- Release Mouse'
|
||||||
print '-- Releasing Mouse'
|
super(MouseResource, cls).release()
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ResourceCounter.__init__(self)
|
super(MouseResource, self).__init__()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
ResourceCounter.__del__(self)
|
super(MouseResource, self).__del__()
|
||||||
|
|
||||||
class CursorResource(ResourceCounter):
|
class CursorResource(ResourceCounter):
|
||||||
"""
|
"""
|
||||||
@ -93,26 +100,38 @@ if __debug__ and __name__ == '__main__':
|
|||||||
resource. Notice how this class also inherits from
|
resource. Notice how this class also inherits from
|
||||||
ResourceCounter. Instead of subclassing MouseCounter,
|
ResourceCounter. Instead of subclassing MouseCounter,
|
||||||
we will just acquire it in our __init__() and release
|
we will just acquire it in our __init__() and release
|
||||||
it in our
|
it in our __del__().
|
||||||
"""
|
"""
|
||||||
@classmethod
|
@classmethod
|
||||||
def acquire(cls):
|
def acquire(cls):
|
||||||
print '-- Acquiring Cursor'
|
super(CursorResource, cls).acquire()
|
||||||
ResourceCounter.acquire()
|
print '-- Acquire Cursor'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def release(cls):
|
def release(cls):
|
||||||
print '-- Releasing Cursor'
|
print '-- Release Cursor'
|
||||||
ResourceCounter.release()
|
super(CursorResource, cls).release()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__mouseResource = MouseResource()
|
self.__mouseResource = MouseResource()
|
||||||
ResourceCounter.__init__(self)
|
super(CursorResource, self).__init__()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
ResourceCounter.__del__(self)
|
super(CursorResource, self).__del__()
|
||||||
del self.__mouseResource
|
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'
|
print '\nAllocate Mouse'
|
||||||
m = MouseResource()
|
m = MouseResource()
|
||||||
print 'Free up Mouse'
|
print 'Free up Mouse'
|
||||||
@ -154,13 +173,21 @@ if __debug__ and __name__ == '__main__':
|
|||||||
del m
|
del m
|
||||||
print 'Free up Cursor'
|
print 'Free up Cursor'
|
||||||
del c
|
del c
|
||||||
|
|
||||||
|
# example of an invalid subclass
|
||||||
|
try:
|
||||||
|
print '\nAllocate Invalid'
|
||||||
|
i = InvalidResource()
|
||||||
|
print 'Free up Invalid'
|
||||||
|
except AssertionError,e:
|
||||||
|
print e
|
||||||
|
|
||||||
def demoFunc():
|
def demoFunc():
|
||||||
print '\nAllocate Cursor within function'
|
print '\nAllocate Cursor within function'
|
||||||
c = CursorResource()
|
c = CursorResource()
|
||||||
|
|
||||||
print 'Cursor will be freed on function exit'
|
print 'Cursor will be freed on function exit'
|
||||||
|
|
||||||
|
|
||||||
demoFunc()
|
demoFunc()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user