annotate Implab/Parallels/SharedLock.cs @ 281:e0916ddc9950 v3 tip

code cleanup and refactoring
author cin
date Fri, 01 Jun 2018 21:35:24 +0300
parents e9e7940c7d98
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
1 using System;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
2 using System.Threading;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
3 using System.Diagnostics;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
4
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
5 namespace Implab.Parallels {
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
6 /// <summary>
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
7 /// Implements a lightweight mechanism to aquire a shared or an exclusive lock.
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
8 /// </summary>
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
9 public class SharedLock {
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
10 readonly object m_lock = new object();
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
11 // the count of locks currently acquired by clients
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
12 int m_locks;
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
13 // the count of pending requests for upgrade
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
14 int m_upgrades;
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
15 bool m_exclusive;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
16
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
17 public bool LockExclusive(int timeout) {
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
18 lock (m_lock) {
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
19 var dt = timeout;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
20 if (m_locks > m_upgrades) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
21 var t1 = Environment.TickCount;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
22 do {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
23 if (!Monitor.Wait(m_lock, timeout))
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
24 return false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
25
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
26 if (m_locks == m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
27 break;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
28
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
29 if (timeout > 0) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
30 dt = timeout - Environment.TickCount + t1;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
31 if (dt < 0)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
32 return false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
33 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
34 } while(true);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
35 }
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
36 m_exclusive = true;
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
37 m_locks ++;
130
671f60cd0250 fixed Resove method bug when calling it on already cancelled promise
cin
parents: 129
diff changeset
38 return true;
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
39 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
40 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
41
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
42 public void LockExclusive() {
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
43 lock (m_lock) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
44
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
45 while (m_locks > m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
46 Monitor.Wait(m_lock);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
47
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
48 m_exclusive = true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
49 m_locks ++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
50 }
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
51 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
52
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
53 /// <summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
54 /// Acquires a shared lock.
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
55 /// </summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
56 /// <returns><c>true</c>, if the shared lock was acquired, <c>false</c> if the specified timeout was expired.</returns>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
57 /// <param name="timeout">Timeout.</param>
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
58 public bool LockShared(int timeout) {
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
59 lock (m_lock) {
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
60 if (!m_exclusive) {
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
61 m_locks++;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
62 return true;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
63 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
64
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
65 if (m_locks == m_upgrades) {
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
66 m_exclusive = false;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
67 m_locks = 1;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
68 return true;
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
69 }
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
70
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
71 var t1 = Environment.TickCount;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
72 var dt = timeout;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
73 do {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
74 if (!Monitor.Wait(m_lock, dt))
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
75 return false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
76
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
77 if (m_locks == m_upgrades || !m_exclusive)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
78 break;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
79
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
80 if (timeout >= 0) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
81 dt = timeout - Environment.TickCount + t1;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
82 if (dt < 0)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
83 return false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
84 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
85 } while(true);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
86
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
87 m_locks ++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
88 m_exclusive = false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
89 return true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
90 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
91 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
92
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
93 /// <summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
94 /// Acquires the shared lock.
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
95 /// </summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
96 public void LockShared() {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
97 lock (m_lock) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
98 if (!m_exclusive) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
99 m_locks++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
100 } else if (m_locks == m_upgrades) {
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
101 m_exclusive = false;
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
102 m_locks++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
103 } else {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
104 while (m_exclusive && m_locks > m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
105 Monitor.Wait(m_lock);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
106
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
107 m_locks++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
108 m_exclusive = false;
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
109 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
110 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
111 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
112
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
113 /// <summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
114 /// Upgrades the current lock to exclusive level.
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
115 /// </summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
116 /// <remarks>If the current lock is exclusive already the method does nothing.</remarks>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
117 public void Upgrade() {
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
118 lock (m_lock) {
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
119 if (!m_exclusive) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
120
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
121 if (m_locks <= m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
122 throw new InvalidOperationException();
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
123
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
124 if (m_locks - m_upgrades == 1) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
125 m_exclusive = true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
126 } else {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
127 m_upgrades++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
128
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
129 while (m_locks > m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
130 Monitor.Wait(m_lock);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
131
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
132 m_upgrades--;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
133 m_exclusive = true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
134 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
135 }
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
136 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
137 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
138
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
139 /// <summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
140 /// Upgrades the current lock to exclusive level.
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
141 /// </summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
142 /// <param name="timeout">Timeout.</param>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
143 /// <returns><c>true</c> if the current lock was updated, <c>false</c> the specified timeout was expired.</returns>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
144 /// <remarks>If the current lock is exclusive already the method does nothing.</remarks>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
145 public bool Upgrade(int timeout) {
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
146 lock (m_lock) {
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
147 if (m_exclusive)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
148 return true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
149 if (m_locks <= m_upgrades)
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
150 throw new InvalidOperationException();
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
151
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
152 if (m_locks - m_upgrades == 1) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
153 m_exclusive = true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
154 } else {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
155 var t1 = Environment.TickCount;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
156 var dt = timeout;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
157 m_upgrades++;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
158 do {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
159 if (!Monitor.Wait(m_lock, dt)) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
160 m_upgrades--;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
161 return false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
162 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
163
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
164 // we may get there but the shared lock already aquired
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
165 if (m_locks == m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
166 break;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
167
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
168 if (timeout >= 0) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
169 dt = timeout - Environment.TickCount + t1;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
170 if (dt < 0) {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
171 m_upgrades--;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
172 return false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
173 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
174 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
175 } while(true);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
176 m_upgrades--;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
177 m_exclusive = true;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
178 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
179 return true;
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
180 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
181 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
182
136
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
183 /// <summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
184 /// Downgrades this lock to shared level.
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
185 /// </summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
186 public void Downgrade() {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
187 lock (m_lock)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
188 m_exclusive = false;
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
189 }
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
190
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
191 /// <summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
192 /// Releases the current lock.
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
193 /// </summary>
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
194 public void Release() {
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
195 lock (m_lock)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
196 // if no more running threads left
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
197 if (--m_locks == m_upgrades)
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
198 Monitor.PulseAll(m_lock);
e9e7940c7d98 shared locks + tests
cin
parents: 130
diff changeset
199 }
129
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
200 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
201 }
471f596b2603 Added SharedLock to synchronization routines
cin
parents:
diff changeset
202