You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.5 KiB
87 lines
2.5 KiB
""" |
|
Synchronization primitives: |
|
|
|
- reader-writer lock (preference to writers) |
|
|
|
(Contributed to Django by eugene@lazutkin.com) |
|
""" |
|
|
|
try: |
|
import threading |
|
except ImportError: |
|
import dummy_threading as threading |
|
|
|
class RWLock: |
|
""" |
|
Classic implementation of reader-writer lock with preference to writers. |
|
|
|
Readers can access a resource simultaneously. |
|
Writers get an exclusive access. |
|
|
|
API is self-descriptive: |
|
reader_enters() |
|
reader_leaves() |
|
writer_enters() |
|
writer_leaves() |
|
""" |
|
def __init__(self): |
|
self.mutex = threading.RLock() |
|
self.can_read = threading.Semaphore(0) |
|
self.can_write = threading.Semaphore(0) |
|
self.active_readers = 0 |
|
self.active_writers = 0 |
|
self.waiting_readers = 0 |
|
self.waiting_writers = 0 |
|
|
|
def reader_enters(self): |
|
self.mutex.acquire() |
|
try: |
|
if self.active_writers == 0 and self.waiting_writers == 0: |
|
self.active_readers += 1 |
|
self.can_read.release() |
|
else: |
|
self.waiting_readers += 1 |
|
finally: |
|
self.mutex.release() |
|
self.can_read.acquire() |
|
|
|
def reader_leaves(self): |
|
self.mutex.acquire() |
|
try: |
|
self.active_readers -= 1 |
|
if self.active_readers == 0 and self.waiting_writers != 0: |
|
self.active_writers += 1 |
|
self.waiting_writers -= 1 |
|
self.can_write.release() |
|
finally: |
|
self.mutex.release() |
|
|
|
def writer_enters(self): |
|
self.mutex.acquire() |
|
try: |
|
if self.active_writers == 0 and self.waiting_writers == 0 and self.active_readers == 0: |
|
self.active_writers += 1 |
|
self.can_write.release() |
|
else: |
|
self.waiting_writers += 1 |
|
finally: |
|
self.mutex.release() |
|
self.can_write.acquire() |
|
|
|
def writer_leaves(self): |
|
self.mutex.acquire() |
|
try: |
|
self.active_writers -= 1 |
|
if self.waiting_writers != 0: |
|
self.active_writers += 1 |
|
self.waiting_writers -= 1 |
|
self.can_write.release() |
|
elif self.waiting_readers != 0: |
|
t = self.waiting_readers |
|
self.waiting_readers = 0 |
|
self.active_readers += t |
|
while t > 0: |
|
self.can_read.release() |
|
t -= 1 |
|
finally: |
|
self.mutex.release()
|
|
|