|
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Transactions;
namespace CachingAppBlock.Transactional
{
/// <summary>
/// Transactional lock class is solely used for thread synchronization
/// </summary>
public class TransactionalLock
{
private static readonly ThreadSafeDictionary<string, TransactionalLock> lockDictionary = new ThreadSafeDictionary<string, TransactionalLock>();
private Synchronizer threadSynchronizer = new Synchronizer();
private TransactionInformation tranInfo;
public static void Lock(string key)
{
if (Transaction.Current != null)
{
if (!lockDictionary.ContainsKey(key))
{
lockDictionary[key] = new TransactionalLock();
}
lockDictionary[key].LockInternal();
}
}
private void LockInternal()
{
if (tranInfo == null)
{
InitializeLock();
}
if (!TransactionsEqual(Transaction.Current.TransactionInformation, tranInfo))
{
threadSynchronizer.Wait();
InitializeLock();
}
}
private void InitializeLock()
{
if(Transaction.Current.IsolationLevel != IsolationLevel.Serializable)
{
throw new InvalidOperationException("Only serializable transactions are supported");
}
tranInfo = Transaction.Current.TransactionInformation;
Transaction.Current.TransactionCompleted +=
(object sender, TransactionEventArgs e) => {
threadSynchronizer.Set();
};
}
private static bool TransactionsEqual(TransactionInformation tran1, TransactionInformation tran2)
{
if (tran1.DistributedIdentifier == Guid.Empty && tran1.DistributedIdentifier == Guid.Empty)
{
return tran1.LocalIdentifier == tran2.LocalIdentifier;
}
return tran1.DistributedIdentifier == tran2.DistributedIdentifier;
}
private class Synchronizer
{
private object lockObject = new object();
private bool canProceed = false;
public void Wait()
{
lock (lockObject)
{
while (!canProceed) Monitor.Wait(lockObject);
canProceed = true;
}
}
public void Set()
{
lock (lockObject)
{
canProceed = true;
Monitor.Pulse(lockObject);
}
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
The views expressed in my articles are mine and do not necessarily reflect the views of my employer.
if(youWantToContactMe)
{
SendMessage(string.Format("{0}@{1}.com", "liptchinski_vit", "yahoo"));
}
More info in my LinkedIn profile:
http://www.linkedin.com/in/vitaliyliptchinsky