##// END OF EJS Templates
fixed promise chaining behavior, the error handler doesn't handle result or cancellation handlers exceptions these exceptions are propagated to the next handlers.
fixed promise chaining behavior, the error handler doesn't handle result or cancellation handlers exceptions these exceptions are propagated to the next handlers.

File last commit:

r136:e9e7940c7d98 v2
r196:40d7fed4a09e default
Show More
SharedLock.cs
202 lines | 6.3 KiB | text/x-csharp | CSharpLexer
cin
Added SharedLock to synchronization routines
r129 using System;
using System.Threading;
using System.Diagnostics;
namespace Implab.Parallels {
/// <summary>
/// Implements a lightweight mechanism to aquire a shared or an exclusive lock.
/// </summary>
public class SharedLock {
readonly object m_lock = new object();
cin
shared locks + tests
r136 // the count of locks currently acquired by clients
cin
Added SharedLock to synchronization routines
r129 int m_locks;
cin
shared locks + tests
r136 // the count of pending requests for upgrade
int m_upgrades;
cin
Added SharedLock to synchronization routines
r129 bool m_exclusive;
public bool LockExclusive(int timeout) {
lock (m_lock) {
cin
shared locks + tests
r136 var dt = timeout;
if (m_locks > m_upgrades) {
var t1 = Environment.TickCount;
do {
if (!Monitor.Wait(m_lock, timeout))
return false;
if (m_locks == m_upgrades)
break;
if (timeout > 0) {
dt = timeout - Environment.TickCount + t1;
if (dt < 0)
return false;
}
} while(true);
}
cin
Added SharedLock to synchronization routines
r129 m_exclusive = true;
cin
shared locks + tests
r136 m_locks ++;
cin
fixed Resove method bug when calling it on already cancelled promise
r130 return true;
cin
Added SharedLock to synchronization routines
r129 }
}
public void LockExclusive() {
cin
shared locks + tests
r136 lock (m_lock) {
while (m_locks > m_upgrades)
Monitor.Wait(m_lock);
m_exclusive = true;
m_locks ++;
}
cin
Added SharedLock to synchronization routines
r129 }
cin
shared locks + tests
r136 /// <summary>
/// Acquires a shared lock.
/// </summary>
/// <returns><c>true</c>, if the shared lock was acquired, <c>false</c> if the specified timeout was expired.</returns>
/// <param name="timeout">Timeout.</param>
cin
Added SharedLock to synchronization routines
r129 public bool LockShared(int timeout) {
lock (m_lock) {
if (!m_exclusive) {
m_locks++;
return true;
}
cin
shared locks + tests
r136 if (m_locks == m_upgrades) {
cin
Added SharedLock to synchronization routines
r129 m_exclusive = false;
m_locks = 1;
return true;
}
cin
shared locks + tests
r136
var t1 = Environment.TickCount;
var dt = timeout;
do {
if (!Monitor.Wait(m_lock, dt))
return false;
if (m_locks == m_upgrades || !m_exclusive)
break;
if (timeout >= 0) {
dt = timeout - Environment.TickCount + t1;
if (dt < 0)
return false;
}
} while(true);
m_locks ++;
m_exclusive = false;
return true;
}
}
/// <summary>
/// Acquires the shared lock.
/// </summary>
public void LockShared() {
lock (m_lock) {
if (!m_exclusive) {
m_locks++;
} else if (m_locks == m_upgrades) {
cin
Added SharedLock to synchronization routines
r129 m_exclusive = false;
cin
shared locks + tests
r136 m_locks++;
} else {
while (m_exclusive && m_locks > m_upgrades)
Monitor.Wait(m_lock);
m_locks++;
m_exclusive = false;
cin
Added SharedLock to synchronization routines
r129 }
}
}
cin
shared locks + tests
r136 /// <summary>
/// Upgrades the current lock to exclusive level.
/// </summary>
/// <remarks>If the current lock is exclusive already the method does nothing.</remarks>
public void Upgrade() {
cin
Added SharedLock to synchronization routines
r129 lock (m_lock) {
cin
shared locks + tests
r136 if (!m_exclusive) {
if (m_locks <= m_upgrades)
throw new InvalidOperationException();
if (m_locks - m_upgrades == 1) {
m_exclusive = true;
} else {
m_upgrades++;
while (m_locks > m_upgrades)
Monitor.Wait(m_lock);
m_upgrades--;
m_exclusive = true;
}
}
cin
Added SharedLock to synchronization routines
r129 }
}
cin
shared locks + tests
r136 /// <summary>
/// Upgrades the current lock to exclusive level.
/// </summary>
/// <param name="timeout">Timeout.</param>
/// <returns><c>true</c> if the current lock was updated, <c>false</c> the specified timeout was expired.</returns>
/// <remarks>If the current lock is exclusive already the method does nothing.</remarks>
public bool Upgrade(int timeout) {
cin
Added SharedLock to synchronization routines
r129 lock (m_lock) {
cin
shared locks + tests
r136 if (m_exclusive)
return true;
if (m_locks <= m_upgrades)
cin
Added SharedLock to synchronization routines
r129 throw new InvalidOperationException();
cin
shared locks + tests
r136
if (m_locks - m_upgrades == 1) {
m_exclusive = true;
} else {
var t1 = Environment.TickCount;
var dt = timeout;
m_upgrades++;
do {
if (!Monitor.Wait(m_lock, dt)) {
m_upgrades--;
return false;
}
// we may get there but the shared lock already aquired
if (m_locks == m_upgrades)
break;
if (timeout >= 0) {
dt = timeout - Environment.TickCount + t1;
if (dt < 0) {
m_upgrades--;
return false;
}
}
} while(true);
m_upgrades--;
m_exclusive = true;
}
return true;
cin
Added SharedLock to synchronization routines
r129 }
}
cin
shared locks + tests
r136 /// <summary>
/// Downgrades this lock to shared level.
/// </summary>
public void Downgrade() {
lock (m_lock)
m_exclusive = false;
}
/// <summary>
/// Releases the current lock.
/// </summary>
public void Release() {
lock (m_lock)
// if no more running threads left
if (--m_locks == m_upgrades)
Monitor.PulseAll(m_lock);
}
cin
Added SharedLock to synchronization routines
r129 }
}