Locking and try/finally
Mike C. Fletcher
mcfletch at rogers.com
Wed Dec 4 12:49:18 EST 2002
Another approach that makes resource-releasing w/out try-finally easy
(but only works properly on CPython) is to create an object like this:
class MyLock( object ):
def __init__( self, mutex ):
self.mutex = mutex
mutex.acquire()
def __del__( self ):
self.release()
def release( self ):
mutex = self.mutex
# minor race condition possible here
# not a problem if mutex.release can be
# called multiple times w/out problem
if mutex is not None:
self.mutex = None
mutex.release()
then use it like this:
def blah():
"""Generic use, whole function is locked"""
lock = MyLock( mutex )
return do_some_processing()
# mutex is released when lock is destroyed
or
def blah2():
"""Show explicit release"""
lock = MyLock( mutex )
do_some_other_things()
lock.release() # explicit release
do_unlocked_things()
lock = MyLock( mutex )
return do_some_other_things_again()
# lazy release again...
The basic idea being to use the local-variable finalisation of the
function to do the finally clause equivalent. Unfortunately, Jython's GC
approach is likely to make it untenable for use there. Oh well.
The pattern (which isn't mine) is especially nice for system resources
like OpenGL display-lists, where you want to store the resource for a
while normally (i.e. lock in the given list), but de-allocate it
immediately if the compilation function fails (in which case you just
don't bother to store it), and need to ensure that the resource is freed
on object deletion regardless. Locks are a little less obviously suited
to the pattern.
Enjoy,
Mike
Geoffrey Talvola wrote:
>xtian at toysinabag.com [mailto:xtian at toysinabag.com] wrote:
>...
>
>
>>Obtaining locks is simpler in C++ than in Python. The equivalent
>>Python code is always 3 lines longer. In fact, about 9% of the Python
>>implementation of Recall is simply obtaining and releasing locks
>>safely. Yet, overall, the Python code is smaller.
>>
>>
>...
>
>Instead of writing:
>
> mutex.acquire()
> try:
> # do something
> finally:
> mutex.release()
>
>How about wrapping up the try/finally and acquire/release into a method of
>the mutex object that takes a callable as its argument:
>
> def task():
> # do something
> mutex.call(task)
>
>This saves 2 lines, as long as the "do something" part can be placed into a
>nested function (which isn't always possible, but often is, using nested
>scopes).
>
>- Geoff
>
>
>
--
_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/
More information about the Python-list
mailing list