Revision 3b7ed473 lib/locking.py
b/lib/locking.py | ||
---|---|---|
372 | 372 |
# Check we don't already own locks at this level |
373 | 373 |
assert not self._is_owned(), "Cannot acquire locks in the same set twice" |
374 | 374 |
|
375 |
if names is None: |
|
376 |
# If no names are given acquire the whole set by not letting new names |
|
377 |
# being added before we release, and getting the current list of names. |
|
378 |
# Some of them may then be deleted later, but we'll cope with this. |
|
379 |
# |
|
380 |
# We'd like to acquire this lock in a shared way, as it's nice if |
|
381 |
# everybody else can use the instances at the same time. If are acquiring |
|
382 |
# them exclusively though they won't be able to do this anyway, though, |
|
383 |
# so we'll get the list lock exclusively as well in order to be able to |
|
384 |
# do add() on the set while owning it. |
|
385 |
self.__lock.acquire(shared=shared) |
|
386 |
|
|
375 | 387 |
try: |
376 | 388 |
# Support passing in a single resource to acquire rather than many |
377 | 389 |
if isinstance(names, basestring): |
378 | 390 |
names = [names] |
379 | 391 |
else: |
392 |
if names is None: |
|
393 |
names = self.__names() |
|
380 | 394 |
names.sort() |
381 | 395 |
|
382 | 396 |
acquire_list = [] |
... | ... | |
388 | 402 |
lock = self.__lockdict[lname] # raises KeyError if the lock is not there |
389 | 403 |
acquire_list.append((lname, lock)) |
390 | 404 |
except (KeyError): |
391 |
raise errors.LockError('non-existing lock in set (%s)' % lname) |
|
405 |
if self.__lock._is_owned(): |
|
406 |
# We are acquiring all the set, it doesn't matter if this particular |
|
407 |
# element is not there anymore. |
|
408 |
continue |
|
409 |
else: |
|
410 |
raise errors.LockError('non-existing lock in set (%s)' % lname) |
|
392 | 411 |
|
393 | 412 |
# This will hold the locknames we effectively acquired. |
394 | 413 |
acquired = set() |
... | ... | |
411 | 430 |
raise |
412 | 431 |
|
413 | 432 |
except (errors.LockError): |
414 |
name_fail = lname |
|
415 |
for lname in self._list_owned(): |
|
416 |
self.__lockdict[lname].release() |
|
417 |
self._del_owned(lname) |
|
418 |
raise errors.LockError('non-existing lock in set (%s)' % name_fail) |
|
433 |
if self.__lock._is_owned(): |
|
434 |
# We are acquiring all the set, it doesn't matter if this particular |
|
435 |
# element is not there anymore. |
|
436 |
continue |
|
437 |
else: |
|
438 |
name_fail = lname |
|
439 |
for lname in self._list_owned(): |
|
440 |
self.__lockdict[lname].release() |
|
441 |
self._del_owned(lname) |
|
442 |
raise errors.LockError('non-existing lock in set (%s)' % name_fail) |
|
419 | 443 |
|
420 | 444 |
except: |
445 |
# If something went wrong and we had the set-lock let's release it... |
|
446 |
if self.__lock._is_owned(): |
|
447 |
self.__lock.release() |
|
421 | 448 |
raise |
422 | 449 |
|
423 | 450 |
return acquired |
... | ... | |
448 | 475 |
"release() on unheld resources %s" % |
449 | 476 |
names.difference(self._list_owned())) |
450 | 477 |
|
478 |
# First of all let's release the "all elements" lock, if set. |
|
479 |
# After this 'add' can work again |
|
480 |
if self.__lock._is_owned(): |
|
481 |
self.__lock.release() |
|
482 |
|
|
451 | 483 |
for lockname in names: |
452 | 484 |
# If we are sure the lock doesn't leave __lockdict without being |
453 | 485 |
# exclusively held we can do this... |
... | ... | |
463 | 495 |
shared: is the pre-acquisition shared? |
464 | 496 |
|
465 | 497 |
""" |
498 |
|
|
499 |
assert not self.__lock._is_owned(shared=1), ( |
|
500 |
"Cannot add new elements while sharing the set-lock") |
|
501 |
|
|
466 | 502 |
# Support passing in a single resource to add rather than many |
467 | 503 |
if isinstance(names, basestring): |
468 | 504 |
names = [names] |
469 | 505 |
|
470 |
# Acquire the internal lock in an exclusive way, so there cannot be a |
|
471 |
# conflicting add() |
|
472 |
self.__lock.acquire() |
|
506 |
# If we don't already own the set-level lock acquire it in an exclusive way |
|
507 |
# we'll get it and note we need to release it later. |
|
508 |
release_lock = False |
|
509 |
if not self.__lock._is_owned(): |
|
510 |
release_lock = True |
|
511 |
self.__lock.acquire() |
|
512 |
|
|
473 | 513 |
try: |
474 | 514 |
invalid_names = set(self.__names()).intersection(names) |
475 | 515 |
if invalid_names: |
... | ... | |
499 | 539 |
self.__lockdict[lockname] = lock |
500 | 540 |
|
501 | 541 |
finally: |
502 |
self.__lock.release() |
|
542 |
# Only release __lock if we were not holding it previously. |
|
543 |
if release_lock: |
|
544 |
self.__lock.release() |
|
503 | 545 |
|
504 | 546 |
return True |
505 | 547 |
|
Also available in: Unified diff