Last active
February 5, 2019 17:10
-
-
Save danielytics/ed88de22fbc6f2fc24955ca9d90ae479 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lock = RWLock() | |
with lock.read(): | |
# Do some stuff | |
# Other threads can also use lock.read() at the same time, but no threads can lock.write() until current reads complete | |
with lock.write(): | |
# Do some stuff | |
# No other thread can be reading or writing while this thread has the lock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import threading | |
class RWLockWrapper: | |
def __init__(self, acquire, release): | |
self.__rwlock_acquire = acquire | |
self.__rwlock_release = release | |
def __enter__(self): | |
self.__rwlock_acquire() | |
def __exit__(self, type, value, traceback): | |
self.__rwlock_release() | |
class RWLock: | |
def __init__(self): | |
self.__write_lock = threading.Lock() | |
self.__readers = threading.Condition() | |
self.__reader_count = 0 | |
def acquire_read(self): | |
# No new readers while writer has the write lock, must wait | |
with self.__write_lock: | |
# Atomically increment the reader count | |
with self.__readers: | |
self.__reader_count += 1 | |
def release_read(self): | |
# Atomically decrement the reader count, if no active readers | |
# then notify waiting writer (if any) | |
with self.__readers: | |
self.__reader_count -= 1 | |
if self.__reader_count == 0: | |
self.__readers.notify() | |
def acquire_write(self): | |
# If this throws, since its expected to be called | |
# in with statement, lock will be released. | |
self.__write_lock.acquire() # Block new readers (and other writers) | |
# Wait until reader count is zero, if not already | |
with self.__readers: | |
while self.__reader_count > 0: | |
self.__readers.wait() | |
def release_write(self): | |
# Done writing, release writer lock | |
self.__write_lock.release() | |
def read(self): | |
return RWLockWrapper(self.acquire_read, self.release_read) | |
def write(self): | |
return RWLockWrapper(self.acquire_write, self.release_write) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment