aboutsummaryrefslogtreecommitdiff
path: root/rwlock.py
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2014-12-27 13:29:20 +0800
committerDeterminant <ted.sybil@gmail.com>2014-12-27 13:29:20 +0800
commit30c896841c65c78cb4cf048c0c26c8e62ee0cf05 (patch)
tree5fb076c5a373b3ffa2e25842f47fe2e64dd7b6bc /rwlock.py
init
Diffstat (limited to 'rwlock.py')
-rw-r--r--rwlock.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/rwlock.py b/rwlock.py
new file mode 100644
index 0000000..8823777
--- /dev/null
+++ b/rwlock.py
@@ -0,0 +1,71 @@
+"""Simple reader-writer locks in Python
+Many readers can hold the lock XOR one and only one writer"""
+import threading
+
+version = """$Id: rwlock.py,v 1.1 2004/12/22 22:32:00 majid Exp $"""
+
+class RWLock:
+ """
+A simple reader-writer lock Several readers can hold the lock
+simultaneously, XOR one writer. Write locks have priority over reads to
+prevent write starvation.
+"""
+ def __init__(self):
+ self.rwlock = 0
+ self.writers_waiting = 0
+ self.monitor = threading.Lock()
+ self.readers_ok = threading.Condition(self.monitor)
+ self.writers_ok = threading.Condition(self.monitor)
+ def acquire_read(self):
+ """Acquire a read lock. Several threads can hold this typeof lock.
+It is exclusive with write locks."""
+ self.monitor.acquire()
+ while self.rwlock < 0 or self.writers_waiting:
+ self.readers_ok.wait()
+ self.rwlock += 1
+ self.monitor.release()
+ def acquire_write(self):
+ """Acquire a write lock. Only one thread can hold this lock, and
+only when no read locks are also held."""
+ self.monitor.acquire()
+ while self.rwlock != 0:
+ self.writers_waiting += 1
+ self.writers_ok.wait()
+ self.writers_waiting -= 1
+ self.rwlock = -1
+ self.monitor.release()
+ def promote(self):
+ """Promote an already-acquired read lock to a write lock
+ WARNING: it is very easy to deadlock with this method"""
+ self.monitor.acquire()
+ self.rwlock -= 1
+ while self.rwlock != 0:
+ self.writers_waiting += 1
+ self.writers_ok.wait()
+ self.writers_waiting -= 1
+ self.rwlock = -1
+ self.monitor.release()
+ def demote(self):
+ """Demote an already-acquired write lock to a read lock"""
+ self.monitor.acquire()
+ self.rwlock = 1
+ self.readers_ok.notifyAll()
+ self.monitor.release()
+ def release(self):
+ """Release a lock, whether read or write."""
+ self.monitor.acquire()
+ if self.rwlock < 0:
+ self.rwlock = 0
+ else:
+ self.rwlock -= 1
+ wake_writers = self.writers_waiting and self.rwlock == 0
+ wake_readers = self.writers_waiting == 0
+ self.monitor.release()
+ if wake_writers:
+ self.writers_ok.acquire()
+ self.writers_ok.notify()
+ self.writers_ok.release()
+ elif wake_readers:
+ self.readers_ok.acquire()
+ self.readers_ok.notifyAll()
+ self.readers_ok.release()