Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 2286 → Rev 2287

/MKLiveView/v1.0/GMap.NET.Core/GMap.NET.Internals/FastReaderWriterLock.cs
0,0 → 1,194
#if !MONO && !PocketPC
#define UseFastResourceLock
#endif
 
namespace GMap.NET.Internals
{
using System;
using System.Threading;
#if !MONO
using System.Runtime.InteropServices;
#endif
 
/// <summary>
/// custom ReaderWriterLock
/// in Vista and later uses integrated Slim Reader/Writer (SRW) Lock
/// http://msdn.microsoft.com/en-us/library/aa904937(VS.85).aspx
/// http://msdn.microsoft.com/en-us/magazine/cc163405.aspx#S2
/// </summary>
public sealed class FastReaderWriterLock : IDisposable
{
#if !MONO && !PocketPC
private static class NativeMethods
{
// Methods
[DllImport("Kernel32", ExactSpelling = true)]
internal static extern void AcquireSRWLockExclusive(ref IntPtr srw);
[DllImport("Kernel32", ExactSpelling = true)]
internal static extern void AcquireSRWLockShared(ref IntPtr srw);
[DllImport("Kernel32", ExactSpelling = true)]
internal static extern void InitializeSRWLock(out IntPtr srw);
[DllImport("Kernel32", ExactSpelling = true)]
internal static extern void ReleaseSRWLockExclusive(ref IntPtr srw);
[DllImport("Kernel32", ExactSpelling = true)]
internal static extern void ReleaseSRWLockShared(ref IntPtr srw);
}
 
IntPtr LockSRW = IntPtr.Zero;
 
public FastReaderWriterLock()
{
if (UseNativeSRWLock)
{
NativeMethods.InitializeSRWLock(out this.LockSRW);
}
else
{
#if UseFastResourceLock
pLock = new FastResourceLock();
#endif
}
}
 
#if UseFastResourceLock
~FastReaderWriterLock()
{
Dispose(false);
}
 
void Dispose(bool disposing)
{
if (pLock != null)
{
pLock.Dispose();
pLock = null;
}
}
 
FastResourceLock pLock;
#endif
 
static readonly bool UseNativeSRWLock = Stuff.IsRunningOnVistaOrLater() && IntPtr.Size == 4; // works only in 32-bit mode, any ideas on native 64-bit support?
 
#endif
 
#if !UseFastResourceLock
Int32 busy = 0;
Int32 readCount = 0;
#endif
 
public void AcquireReaderLock()
{
#if !MONO && !PocketPC
if (UseNativeSRWLock)
{
NativeMethods.AcquireSRWLockShared(ref LockSRW);
}
else
#endif
{
#if UseFastResourceLock
pLock.AcquireShared();
#else
Thread.BeginCriticalRegion();
 
while(Interlocked.CompareExchange(ref busy, 1, 0) != 0)
{
Thread.Sleep(1);
}
 
Interlocked.Increment(ref readCount);
 
// somehow this fix deadlock on heavy reads
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
 
Interlocked.Exchange(ref busy, 0);
#endif
}
}
 
public void ReleaseReaderLock()
{
#if !MONO && !PocketPC
if (UseNativeSRWLock)
{
NativeMethods.ReleaseSRWLockShared(ref LockSRW);
}
else
#endif
{
#if UseFastResourceLock
pLock.ReleaseShared();
#else
Interlocked.Decrement(ref readCount);
Thread.EndCriticalRegion();
#endif
}
}
 
public void AcquireWriterLock()
{
#if !MONO && !PocketPC
if (UseNativeSRWLock)
{
NativeMethods.AcquireSRWLockExclusive(ref LockSRW);
}
else
#endif
{
#if UseFastResourceLock
pLock.AcquireExclusive();
#else
Thread.BeginCriticalRegion();
 
while(Interlocked.CompareExchange(ref busy, 1, 0) != 0)
{
Thread.Sleep(1);
}
 
while(Interlocked.CompareExchange(ref readCount, 0, 0) != 0)
{
Thread.Sleep(1);
}
#endif
}
}
 
public void ReleaseWriterLock()
{
#if !MONO && !PocketPC
if (UseNativeSRWLock)
{
NativeMethods.ReleaseSRWLockExclusive(ref LockSRW);
}
else
#endif
{
#if UseFastResourceLock
pLock.ReleaseExclusive();
#else
Interlocked.Exchange(ref busy, 0);
Thread.EndCriticalRegion();
#endif
}
}
 
#region IDisposable Members
 
public void Dispose()
{
#if UseFastResourceLock
this.Dispose(true);
GC.SuppressFinalize(this);
#endif
}
 
#endregion
}
}