Skip to content

Instantly share code, notes, and snippets.

@danielytics
Last active February 5, 2019 17:10
Show Gist options
  • Save danielytics/ed88de22fbc6f2fc24955ca9d90ae479 to your computer and use it in GitHub Desktop.
Save danielytics/ed88de22fbc6f2fc24955ca9d90ae479 to your computer and use it in GitHub Desktop.
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
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