~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/counted_lock.py

  • Committer: Vincent Ladeuil
  • Date: 2009-06-22 12:52:39 UTC
  • mto: (4471.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4472.
  • Revision ID: v.ladeuil+lp@free.fr-20090622125239-kabo9smxt9c3vnir
Use a consistent scheme for naming pyrex source files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
 
1
# Copyright (C) 2007, 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Counted lock class"""
18
18
 
19
19
 
20
 
from bzrlib.errors import (
21
 
    LockError,
22
 
    ReadOnlyError,
 
20
from bzrlib import (
 
21
    errors,
23
22
    )
24
23
 
25
24
 
26
 
# TODO: Pass through lock tokens on lock_write and read, and return them...
27
 
#
28
 
# TODO: Allow upgrading read locks to write?  Conceptually difficult.
29
 
 
30
 
 
31
25
class CountedLock(object):
32
26
    """Decorator around a lock that makes it reentrant.
33
27
 
34
28
    This can be used with any object that provides a basic Lock interface,
35
29
    including LockDirs and OS file locks.
 
30
 
 
31
    :ivar _token: While a write lock is held, this is the token 
 
32
        for it.
36
33
    """
37
34
 
38
35
    def __init__(self, real_lock):
40
37
        self._lock_mode = None
41
38
        self._lock_count = 0
42
39
 
 
40
    def __repr__(self):
 
41
        return "%s(%r)" % (self.__class__.__name__,
 
42
            self._real_lock)
 
43
 
43
44
    def break_lock(self):
44
45
        self._real_lock.break_lock()
45
46
        self._lock_mode = None
62
63
            self._lock_count = 1
63
64
            self._lock_mode = 'r'
64
65
 
65
 
    def lock_write(self):
 
66
    def lock_write(self, token=None):
66
67
        """Acquire the lock in write mode.
67
68
 
68
69
        If the lock was originally acquired in read mode this will fail.
 
70
 
 
71
        :param token: If given and the lock is already held, 
 
72
            then validate that we already hold the real
 
73
            lock with this token.
 
74
 
 
75
        :returns: The token from the underlying lock.
69
76
        """
70
77
        if self._lock_count == 0:
71
 
            self._real_lock.lock_write()
 
78
            self._token = self._real_lock.lock_write(token=token)
72
79
            self._lock_mode = 'w'
 
80
            self._lock_count += 1
 
81
            return self._token
73
82
        elif self._lock_mode != 'w':
74
 
            raise ReadOnlyError(self)
75
 
        self._lock_count += 1
 
83
            raise errors.ReadOnlyError(self)
 
84
        else:
 
85
            self._real_lock.validate_token(token)
 
86
            self._lock_count += 1
 
87
            return self._token
76
88
 
77
89
    def unlock(self):
78
90
        if self._lock_count == 0:
79
 
            raise LockError("%s not locked" % (self,))
 
91
            raise errors.LockNotHeld(self)
80
92
        elif self._lock_count == 1:
 
93
            # these are decremented first; if we fail to unlock the most
 
94
            # reasonable assumption is that we still don't have the lock
 
95
            # anymore
 
96
            self._lock_mode = None
 
97
            self._lock_count -= 1
81
98
            self._real_lock.unlock()
82
 
            self._lock_mode = None
83
 
        self._lock_count -= 1
 
99
        else:
 
100
            self._lock_count -= 1