[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] xend: Add a multi-reader-single-writer lock implementation



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1225880539 0
# Node ID 484cf12ba667a3d2077bda3df24177ace78ff3fe
# Parent  4bfc67b09e9c4bf99adfd6623cb66945c1b661cf
xend: Add a multi-reader-single-writer lock implementation

This patch adds a reader-writer lock primitive to xend since python
does not provide it by default. The implementation is based on a
condition variable. Some test code is appended at the end of the file.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 tools/python/xen/util/rwlock.py |  137 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 137 insertions(+)

diff -r 4bfc67b09e9c -r 484cf12ba667 tools/python/xen/util/rwlock.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/util/rwlock.py   Wed Nov 05 10:22:19 2008 +0000
@@ -0,0 +1,137 @@
+""" Reader-writer lock implementation based on a condition variable """
+
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2008 International Business Machines Corp.
+# Author: Stefan Berger <stefanb@xxxxxxxxxx>
+#============================================================================
+
+from threading import Condition
+
+class RWLock:
+
+    RWLOCK_STATE_WRITER = -1
+    RWLOCK_STATE_UNUSED = 0
+
+    def __init__(self):
+        self.__condition = Condition()
+        self.__state = RWLock.RWLOCK_STATE_UNUSED
+        self.__blocked_writers = 0
+
+    def acquire_reader(self):
+        self.__condition.acquire()
+        while True:
+            if self.__state == RWLock.RWLOCK_STATE_WRITER:
+                self.__condition.wait()
+            else:
+                break
+        self.__state += 1
+        self.__condition.release()
+
+    def acquire_writer(self):
+        self.__condition.acquire()
+        self.__acquire_writer(RWLock.RWLOCK_STATE_UNUSED)
+        self.__condition.release()
+
+    def __acquire_writer(self, wait_for_state):
+        while True:
+            if self.__state == wait_for_state:
+                self.__state = RWLock.RWLOCK_STATE_WRITER
+                break
+            else:
+                self.__blocked_writers += 1
+                self.__condition.wait()
+                self.__blocked_writers -= 1
+
+    def release(self):
+        self.__condition.acquire()
+        if self.__state == RWLock.RWLOCK_STATE_WRITER:
+            self.__state = RWLock.RWLOCK_STATE_UNUSED
+        elif self.__state == RWLock.RWLOCK_STATE_UNUSED:
+            assert False, 'Lock not in use.'
+        else:
+            self.__state -= 1
+        self.__condition.notifyAll()
+        self.__condition.release()
+
+
+if __name__ == '__main__':
+    from threading import Thread
+    from time import sleep
+
+    rwlock = RWLock()
+
+    class Base(Thread):
+        def __init__(self, name, timeout):
+            self.name = name
+            self.timeout = timeout
+            Thread.__init__(self)
+
+    class Reader(Base):
+        def __init__(self, name = 'Reader', timeout = 10):
+            Base.__init__(self, name, timeout)
+
+        def run(self):
+            print '%s begin' % self.name
+            rwlock.acquire_reader()
+            print '%s acquired' % self.name
+            sleep(self.timeout)
+            rwlock.release()
+            print '%s end' % self.name
+
+    class ReaderTwice(Base):
+        def __init__(self, name = 'Reader', timeout = 10):
+            Base.__init__(self, name, timeout)
+
+        def run(self):
+            print '%s begin' % self.name
+            rwlock.acquire_reader()
+            print '%s acquired once' % self.name
+            sleep(self.timeout)
+            rwlock.acquire_reader()
+            print '%s acquired twice' % self.name
+            sleep(self.timeout)
+            rwlock.release()
+            rwlock.release()
+            print '%s end' % self.name
+
+    class Writer(Base):
+        def __init__(self, name = 'Writer', timeout = 10):
+            Base.__init__(self, name, timeout)
+
+        def run(self):
+            print '%s begin' % self.name
+            rwlock.acquire_writer()
+            print '%s acquired' % self.name
+            sleep(self.timeout)
+            rwlock.release()
+            print '%s end' % self.name
+
+    def run_test(threadlist, msg):
+        print msg
+        for t in threadlist:
+            t.start()
+            sleep(1)
+        for t in threads:
+            t.join()
+        print 'Done\n\n'
+
+    threads = []
+    threads.append( Reader('R1', 4) )
+    threads.append( Reader('R2', 4) )
+    threads.append( Writer('W1', 4) )
+    threads.append( Reader('R3', 4) )
+    run_test(threads,
+             'Test: readers may bypass blocked writers')

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.