diff options
author | Determinant <ted.sybil@gmail.com> | 2014-12-27 13:29:20 +0800 |
---|---|---|
committer | Determinant <ted.sybil@gmail.com> | 2014-12-27 13:29:20 +0800 |
commit | 30c896841c65c78cb4cf048c0c26c8e62ee0cf05 (patch) | |
tree | 5fb076c5a373b3ffa2e25842f47fe2e64dd7b6bc /rwlock.py |
init
Diffstat (limited to 'rwlock.py')
-rw-r--r-- | rwlock.py | 71 |
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() |