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