1 import threading
2
3
4
5 __author__ = "Mateusz Kobos"
6
7 """
8 This code is a derivative of the code from ActiveState Code service at the address:
9 http://code.activestate.com/recipes/577803-reader-writer-lock-with-priority-for-writers
10 and is licensed under the MIT license.
11 """
12
14 """Synchronization object used in a solution of so-called second
15 readers-writers problem. In this problem, many readers can simultaneously
16 access a share, and a writer has an exclusive access to this share.
17 Additionally, the following constraints should be met:
18 - no reader should be kept waiting if the share is currently opened for
19 reading unless a writer is also waiting for the share,
20 - no writer should be kept waiting for the share longer than absolutely
21 necessary.
22
23 The implementation is based on [1, secs. 4.2.2, 4.2.6, 4.2.7]
24 with a modification -- adding an additional lock (C{self.__readers_queue})
25 -- in accordance with [2].
26
27 Sources:
28 1. A.B. Downey: "The little book of semaphores", Version 2.1.5, 2008
29 2. P.J. Courtois, F. Heymans, D.L. Parnas:
30 "Concurrent Control with 'Readers' and 'Writers'",
31 Communications of the ACM, 1971 (via [3])
32 3. http://en.wikipedia.org/wiki/Readers-writers_problem
33 """
34
36 self.__read_switch = _LightSwitch()
37 self.__write_switch = _LightSwitch()
38 self.__no_readers = threading.Lock()
39 self.__no_writers = threading.Lock()
40 self.__readers_queue = threading.Lock()
41 """A lock giving an even higher priority to the writer in certain
42 cases (see [2] for a discussion)"""
43
45
46
47 self.__readers_queue.acquire()
48
49 self.__no_readers.acquire()
50
51 self.__read_switch.acquire(self.__no_writers)
52
53 self.__no_readers.release()
54
55 self.__readers_queue.release()
56
57
58
60
61
62 self.__read_switch.release(self.__no_writers)
63
64
65
67
68
69 self.__write_switch.acquire(self.__no_readers)
70
71 self.__no_writers.acquire()
72
73
74
76
77
78 self.__no_writers.release()
79 self.__write_switch.release(self.__no_readers)
80
81
82
83
85 """An auxiliary "light switch"-like object. The first thread turns on the
86 "switch", the last one turns it off (see [1, sec. 4.2.2] for details)."""
88 self.__counter = 0
89 self.__mutex = threading.Lock()
90
92 self.__mutex.acquire()
93 self.__counter += 1
94 if self.__counter == 1:
95 lock.acquire()
96 self.__mutex.release()
97
99 self.__mutex.acquire()
100 self.__counter -= 1
101 if self.__counter == 0:
102 lock.release()
103 self.__mutex.release()
104