[PATCH 1 of 5] made repo locks recursive and deprecate refcounting based lock releasing

Ronny Pfannschmidt Ronny.Pfannschmidt at gmx.de
Mon Apr 20 14:50:10 CDT 2009


# HG changeset patch
# User Ronny Pfannschmidt <Ronny.Pfannschmidt at gmx.de>
# Date 1240241185 -7200
# Node ID 384972244ed4c1b00c40185b0456d67457aa0cc9
# Parent  404a2c318e70ae4544a2114021889888dcef9f14
made repo locks recursive and deprecate refcounting based lock releasing

all locks should use the explicit lock.release

mercurial.lock.lock.__del__ handles unwrapping recursive locks

localrepo.lock/wlock are still using weakref in order to keep backward
compatibiltiy to releasing locks via garbage collection
by ensuring the release on __del__

diff -r 404a2c318e70 -r 384972244ed4 mercurial/localrepo.py
--- a/mercurial/localrepo.py	Mon Apr 20 12:25:45 2009 +0200
+++ b/mercurial/localrepo.py	Mon Apr 20 17:26:25 2009 +0200
@@ -683,8 +683,10 @@ class localrepository(repo.repository):
         return l
 
     def lock(self, wait=True):
-        if self._lockref and self._lockref():
-            return self._lockref()
+        l = self._lockref and self._lockref()
+        if l is not None and l.held:
+            l.lock()
+            return l
 
         l = self._lock(self.sjoin("lock"), wait, None, self.invalidate,
                        _('repository %s') % self.origroot)
@@ -692,8 +694,10 @@ class localrepository(repo.repository):
         return l
 
     def wlock(self, wait=True):
-        if self._wlockref and self._wlockref():
-            return self._wlockref()
+        l = self._wlockref and self._wlockref()
+        if l is not None and l.held:
+            l.lock()
+            return l
 
         l = self._lock(self.join("wlock"), wait, self.dirstate.write,
                        self.dirstate.invalidate, _('working directory of %s') %
diff -r 404a2c318e70 -r 384972244ed4 mercurial/lock.py
--- a/mercurial/lock.py	Mon Apr 20 12:25:45 2009 +0200
+++ b/mercurial/lock.py	Mon Apr 20 17:26:25 2009 +0200
@@ -6,6 +6,7 @@
 # of the GNU General Public License, incorporated herein by reference.
 
 import errno, os, socket, time, util, error
+import warnings
 
 class lock(object):
     # lock is symlink on platforms that support it, file on others.
@@ -27,6 +28,11 @@ class lock(object):
         self.lock()
 
     def __del__(self):
+        if self.held:
+            # ensure the lock will be removed
+            # even if recursive locking did occur
+            self.held = 1
+
         self.release()
 
     def lock(self):
@@ -45,6 +51,9 @@ class lock(object):
                                      inst.locker)
 
     def trylock(self):
+        if self.held:
+            self.held += 1
+            return
         if lock._host is None:
             lock._host = socket.gethostname()
         lockname = '%s:%s' % (lock._host, os.getpid())
@@ -97,7 +106,9 @@ class lock(object):
             return locker
 
     def release(self):
-        if self.held:
+        if self.held > 1:
+            self.held -= 1
+        elif self.held is 1:
             self.held = 0
             if self.releasefn:
                 self.releasefn()
@@ -105,3 +116,8 @@ class lock(object):
                 os.unlink(self.f)
             except: pass
 
+def release(*locks):
+    for lock in locks:
+        if lock is not None:
+            lock.release()
+


More information about the Mercurial-devel mailing list