OLD | NEW |
(Empty) | |
| 1 """ |
| 2 Synchronization primitives: |
| 3 |
| 4 - reader-writer lock (preference to writers) |
| 5 |
| 6 (Contributed to Django by eugene@lazutkin.com) |
| 7 """ |
| 8 |
| 9 import contextlib |
| 10 import threading |
| 11 |
| 12 |
| 13 class RWLock(object): |
| 14 """ |
| 15 Classic implementation of reader-writer lock with preference to writers. |
| 16 |
| 17 Readers can access a resource simultaneously. |
| 18 Writers get an exclusive access. |
| 19 |
| 20 API is self-descriptive: |
| 21 reader_enters() |
| 22 reader_leaves() |
| 23 writer_enters() |
| 24 writer_leaves() |
| 25 """ |
| 26 def __init__(self): |
| 27 self.mutex = threading.RLock() |
| 28 self.can_read = threading.Semaphore(0) |
| 29 self.can_write = threading.Semaphore(0) |
| 30 self.active_readers = 0 |
| 31 self.active_writers = 0 |
| 32 self.waiting_readers = 0 |
| 33 self.waiting_writers = 0 |
| 34 |
| 35 def reader_enters(self): |
| 36 with self.mutex: |
| 37 if self.active_writers == 0 and self.waiting_writers == 0: |
| 38 self.active_readers += 1 |
| 39 self.can_read.release() |
| 40 else: |
| 41 self.waiting_readers += 1 |
| 42 self.can_read.acquire() |
| 43 |
| 44 def reader_leaves(self): |
| 45 with self.mutex: |
| 46 self.active_readers -= 1 |
| 47 if self.active_readers == 0 and self.waiting_writers != 0: |
| 48 self.active_writers += 1 |
| 49 self.waiting_writers -= 1 |
| 50 self.can_write.release() |
| 51 |
| 52 @contextlib.contextmanager |
| 53 def reader(self): |
| 54 self.reader_enters() |
| 55 try: |
| 56 yield |
| 57 finally: |
| 58 self.reader_leaves() |
| 59 |
| 60 def writer_enters(self): |
| 61 with self.mutex: |
| 62 if self.active_writers == 0 and self.waiting_writers == 0 and self.a
ctive_readers == 0: |
| 63 self.active_writers += 1 |
| 64 self.can_write.release() |
| 65 else: |
| 66 self.waiting_writers += 1 |
| 67 self.can_write.acquire() |
| 68 |
| 69 def writer_leaves(self): |
| 70 with self.mutex: |
| 71 self.active_writers -= 1 |
| 72 if self.waiting_writers != 0: |
| 73 self.active_writers += 1 |
| 74 self.waiting_writers -= 1 |
| 75 self.can_write.release() |
| 76 elif self.waiting_readers != 0: |
| 77 t = self.waiting_readers |
| 78 self.waiting_readers = 0 |
| 79 self.active_readers += t |
| 80 while t > 0: |
| 81 self.can_read.release() |
| 82 t -= 1 |
| 83 |
| 84 @contextlib.contextmanager |
| 85 def writer(self): |
| 86 self.writer_enters() |
| 87 try: |
| 88 yield |
| 89 finally: |
| 90 self.writer_leaves() |
OLD | NEW |