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