Locking and try/finally

Ype Kingma ykingma at accessforall.nl
Thu Dec 5 03:57:46 EST 2002


xtian wrote:

> Hi -
> 
> While reading http://www.metaslash.com/brochure/recall.html I was
> interested by the following observation:
> 
> [quote]
> Although it would appear that the C++ version is always more complex
> and more verbose than Python, there are times when C++ is shorter and
> more convenient. A useful idiom for threaded applications is a mutex
> variable that protects data from simultaneous updates. In Python, the
> code looks something like this:

<snip code>

> 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.
> [/quote]
> 
> It seemed to me that, given the reference counting basis of Python GC,
> a class with a __del__ method would behave roughly the same:

<snip more code>

> This is alright, though, I think, as long as you aren't storing the
> traceback away somewhere, like the interactive interpreter does with
> the last traceback here. Once it stops being the last traceback (when
> I raise the second exception), the __del__ still runs.
> 
> Is there anything else?
> 
> (Hmm, it doesn't work in Jython, due to Java's gc not refcounting. I

Which is perhaps why __del__ is _not_ guaranteed to be called in the python 
language definition. Refcounting is not the most efficient way of
garbage collecting, but it works well CPython.

> guess that would make it a bad idea. Can you really do much
> crossplatform work between Jython and CPython, though? Would you want
> to (rather than using Jython for access to Java libraries, which
> obviously aren't going to be available to CPython)?)

I wouldn't count on that, the java python extension already exists:
http://sourceforge.net/projects/jpe
 
> And I suppose there's the fact that anyone unfamiliar with the
> ConvenientLock idiom would think that the code wasn't mutexed at all.
> Not as explicit as it could be.
> 
> That said, if you had a significant chunk of your code in a large
> project (large enough to support project-level idioms) riddled with
> try/finally blocks doing this, and you didn't need to worry about
> tracebacks, might it be worthwhile?
> 
> Just an idle thought, really.

I've had this problem, in jython. I solved it by using methods
with the try/finally statements which in turn call other methods
passed as arguments:

def callLocked(l, fun, funArgs):
    l.lock()
    try:
        return apply(fun, funArgs)
    finally:
        l.unlock()

This will let you get rid of all those other try/finally lines.
One could also use the *funArgs idiom.

Btw. Jython 2.1 has a bug when returning from nested try finally's,
ie. for a single syntactical level of try/finally the return works ok.,
but for multiple syntactical levels of try/finally not all finally clauses 
are executed. When I needed multiple locks I encountered the bug.
Since one of the locks was a read lock this wasn't a nice experience.
The workaround is simple, just save the return value and return
after the last finally. The bug was fixed in the meantime, but
Jython 2.2 is not yet available.

Regards,
Ype


-- 
email at xs4all.nl



More information about the Python-list mailing list