diff --git a/direct/src/showbase/ResourceCounter.py b/direct/src/showbase/ResourceCounter.py index 55fe09d797..a22911ba58 100755 --- a/direct/src/showbase/ResourceCounter.py +++ b/direct/src/showbase/ResourceCounter.py @@ -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() + +