I'm trying to understand the logic behind how this class was written, and when I should and shouldn't use it. Any insight would be appreciated
internal struct SpinLock
{
private volatile int lockHeld;
private readonly static int processorCount;
public bool IsHeld
{
get
{
return this.lockHeld != 0;
}
}
static SpinLock()
{
SpinLock.processorCount = Environment.ProcessorCount;
}
public void Enter()
{
if (Interlocked.CompareExchange(ref this.lockHeld, 1, 0) != 0)
{
this.EnterSpin();
}
}
private void EnterSpin()
{
int num = 0;
while (this.lockHeld != null || Interlocked.CompareExchange(ref this.lockHeld, 1, 0) != 0)
{
if (num >= 20 || SpinLock.processorCount <= 1)
{
if (num >= 25)
{
Thread.Sleep(1);
}
else
{
Thread.Sleep(0);
}
}
else
{
Thread.SpinWait(100);
}
num++;
}
}
public void Exit()
{
this.lockHeld = 0;
}
}
Update: I found a sample usage in my source code... This indicates how to use the above object, though I don't understand "why"
internal class FastReaderWriterLock
{
private SpinLock myLock;
private uint numReadWaiters;
private uint numWriteWaiters;
private int owners;
private EventWaitHandle readEvent;
private EventWaitHandle writeEvent;
public FastReaderWriterLock()
{
}
public void AcquireReaderLock(int millisecondsTimeout)
{
this.myLock.Enter();
while (this.owners < 0 || this.numWriteWaiters != 0)
{
if (this.readEvent != null)
{
this.WaitOnEvent(this.readEvent, ref this.numReadWaiters, millisecondsTimeout);
}
else
{
this.LazyCreateEvent(ref this.readEvent, false);
}
}
FastReaderWriterLock fastReaderWriterLock = this;
fastReaderWriterLock.owners = fastReaderWriterLock.owners + 1;
this.myLock.Exit();
}
private void WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, int millisecondsTimeout)
{
waitEvent.Reset();
uint& numPointer = numWaiters;
bool flag = false;
this.myLock.Exit();
try
{
if (waitEvent.WaitOne(millisecondsTimeout, false))
{
flag = true;
}
else
{
throw new TimeoutException("ReaderWriterLock timeout expired");
}
}
finally
{
this.myLock.Enter();
uint& numPointer1 = numWaiters;
if (!flag)
{
this.myLock.Exit();
}
}
}
}