|
|
@@ -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()
|
|
|
+
|
|
|
+
|