# 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
|