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