nrlock.py revision 2029
1516N/A#!/usr/bin/python
1271N/A#
1271N/A# CDDL HEADER START
1271N/A#
1271N/A# The contents of this file are subject to the terms of the
1271N/A# Common Development and Distribution License (the "License").
1271N/A# You may not use this file except in compliance with the License.
1271N/A#
1271N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1271N/A# or http://www.opensolaris.org/os/licensing.
1271N/A# See the License for the specific language governing permissions
1271N/A# and limitations under the License.
1271N/A#
1271N/A# When distributing Covered Code, include this CDDL HEADER in each
1271N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1271N/A# If applicable, add the following below this CDDL HEADER, with the
1271N/A# fields enclosed by brackets "[]" replaced with your own identifying
1271N/A# information: Portions Copyright [yyyy] [name of copyright owner]
1271N/A#
1271N/A# CDDL HEADER END
1271N/A#
2029N/A# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1271N/A#
1271N/A
2029N/Aimport sys
1271N/Aimport threading
2029N/Aimport traceback
1271N/A
1271N/A# Rename some stuff so "from pkg.nrlock import *" is safe
1271N/A__all__ = [ 'NRLock' ]
1271N/A
1271N/Adef NRLock(*args, **kwargs):
2029N/A return _NRLock(*args, **kwargs)
1271N/A
1271N/Aclass _NRLock(threading._RLock):
2029N/A """Interface and implementation for Non-Reentrant locks. Derived from
2029N/A RLocks (which are reentrant locks). The default Python base locking
2029N/A type, threading.Lock(), is non-reentrant but it doesn't support any
2029N/A operations other than aquire() and release(), and we'd like to be
2029N/A able to support things like RLocks._is_owned() so that we can "assert"
2029N/A lock ownership assumptions in our code."""
2029N/A
2029N/A def __init__(self, verbose=None):
2029N/A threading._RLock.__init__(self, verbose)
1271N/A
2029N/A def acquire(self, blocking=1):
2029N/A if self._is_owned():
2029N/A raise NRLockException("Recursive NRLock acquire")
2029N/A rval = threading._RLock.acquire(self, blocking)
2029N/A if rval:
2029N/A self.__locked = True
2029N/A return rval
2029N/A
2029N/A @property
2029N/A def locked(self):
2029N/A """A boolean indicating whether the lock is currently locked."""
2029N/A return self.__locked
1271N/A
2029N/A def _debug_lock_release(self):
2029N/A errbuf = ""
2029N/A owner = self._RLock__owner
2029N/A if not owner:
2029N/A return errbuf
2028N/A
2029N/A # Get stack of current owner, if lock is owned.
2029N/A for tid, stack in sys._current_frames().items():
2029N/A if tid != owner.ident:
2029N/A continue
2029N/A errbuf += "Stack of owner:\n"
2029N/A for filenm, lno, func, txt in \
2029N/A traceback.extract_stack(stack):
2029N/A errbuf += " File: \"%s\", line %d,in %s" \
2029N/A % (filenm, lno, func)
2029N/A if txt:
2029N/A errbuf += "\n %s" % txt.strip()
2029N/A errbuf += "\n"
2029N/A break
2028N/A
2029N/A return errbuf
2029N/A
2029N/A def release(self):
2029N/A try:
2029N/A if self._is_owned():
2029N/A self.__locked = False
2029N/A threading._RLock.release(self)
2029N/A except RuntimeError:
2029N/A errbuf = "Release of unacquired lock\n"
2029N/A errbuf += self._debug_lock_release()
2029N/A raise NRLockException(errbuf)
1271N/A
1693N/Aclass NRLockException(Exception):
1271N/A
2029N/A def __init__(self, *args, **kwargs):
2029N/A if args:
2029N/A self.data = args[0]
2029N/A else:
2029N/A self.data = None
2029N/A self._args = kwargs
2029N/A
2029N/A def __str__(self):
2029N/A return str(self.data)