~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/counted_lock.py

  • Committer: Aaron Bentley
  • Date: 2007-06-21 01:58:29 UTC
  • mto: This revision was merged to the branch mainline in revision 2542.
  • Revision ID: aaron.bentley@utoronto.ca-20070621015829-b62l2d1ehuvgnr3x
Fix iter_topo_order to permit un-included parents

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Counted lock class"""
18
18
 
19
19
 
20
 
from bzrlib import (
21
 
    errors,
 
20
from bzrlib.errors import (
 
21
    LockError,
 
22
    ReadOnlyError,
22
23
    )
23
24
 
24
25
 
 
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
 
25
31
class CountedLock(object):
26
32
    """Decorator around a lock that makes it reentrant.
27
33
 
28
34
    This can be used with any object that provides a basic Lock interface,
29
35
    including LockDirs and OS file locks.
30
 
 
31
 
    :ivar _token: While a write lock is held, this is the token 
32
 
        for it.
33
36
    """
34
37
 
35
38
    def __init__(self, real_lock):
37
40
        self._lock_mode = None
38
41
        self._lock_count = 0
39
42
 
40
 
    def __repr__(self):
41
 
        return "%s(%r)" % (self.__class__.__name__,
42
 
            self._real_lock)
43
 
 
44
43
    def break_lock(self):
45
44
        self._real_lock.break_lock()
46
45
        self._lock_mode = None
57
56
        it is taken in read mode.
58
57
        """
59
58
        if self._lock_mode:
 
59
            assert self._lock_mode in ('r', 'w'), \
 
60
                   "invalid lock mode %r" % self._lock_mode
60
61
            self._lock_count += 1
61
62
        else:
 
63
            assert self._lock_count == 0
62
64
            self._real_lock.lock_read()
63
65
            self._lock_count = 1
64
66
            self._lock_mode = 'r'
65
67
 
66
 
    def lock_write(self, token=None):
 
68
    def lock_write(self):
67
69
        """Acquire the lock in write mode.
68
70
 
69
71
        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.
76
72
        """
77
73
        if self._lock_count == 0:
78
 
            self._token = self._real_lock.lock_write(token=token)
 
74
            assert self._lock_mode is None
 
75
            self._real_lock.lock_write()
79
76
            self._lock_mode = 'w'
80
 
            self._lock_count += 1
81
 
            return self._token
82
77
        elif self._lock_mode != 'w':
83
 
            raise errors.ReadOnlyError(self)
84
 
        else:
85
 
            self._real_lock.validate_token(token)
86
 
            self._lock_count += 1
87
 
            return self._token
 
78
            raise ReadOnlyError(self)
 
79
        self._lock_count += 1
88
80
 
89
81
    def unlock(self):
90
82
        if self._lock_count == 0:
91
 
            raise errors.LockNotHeld(self)
 
83
            raise LockError("%s not locked" % (self,))
92
84
        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
 
85
            self._real_lock.unlock()
96
86
            self._lock_mode = None
97
 
            self._lock_count -= 1
98
 
            self._real_lock.unlock()
99
 
        else:
100
 
            self._lock_count -= 1
 
87
        self._lock_count -= 1