Skip to content

Instantly share code, notes, and snippets.

@uzzu
Last active December 20, 2015 15:19
Show Gist options
  • Select an option

  • Save uzzu/6153170 to your computer and use it in GitHub Desktop.

Select an option

Save uzzu/6153170 to your computer and use it in GitHub Desktop.
The read-write lock object which operates in the "Micro mscorlib" environment of Unity3D, and uses it for execution of a critical section.
using System;
using System.Threading;
public sealed class ReadWriteLock
{
#region Properties
public string Name { get; private set; }
#endregion
#region Fields
static readonly System.Object lifecycleLock = new System.Object();
static Dictionary<string, ReadWriteLock> created = new Dictionary<string, ReadWriteLock>();
static int serial = 0;
readonly System.Object internalLock;
int readerCount;
bool isWriting;
#endregion
#region Lifecycle
public static ReadWriteLock Create<T>(bool instanceUnique = false)
{
var type = typeof(T);
return Create(type.FullName, instanceUnique);
}
public static ReadWriteLock Create(string name, bool instanceUnique = false)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("name was null or empty");
}
lock (lifecycleLock)
{
if (instanceUnique)
{
serial++;
name = name + serial.ToString();
}
if (!created.ContainsKey(name))
{
var result = new ReadWriteLock(name);
created[name] = result;
}
return created[name];
}
}
public static void Delete(ReadWriteLock that)
{
Delete(that.Name);
}
public static void Delete(string name)
{
if (string.IsNullOrEmpty(name))
{
return;
}
lock (lifecycleLock)
{
if (!created.ContainsKey(name))
{
return;
}
created.Remove(name);
}
}
public static void DeleteAll()
{
lock (lifecycleLock)
{
created.RemoveAll();
}
}
#endregion
#region Constructor
ReadWriteLock(string name)
{
Name = name;
internalLock = new System.Object();
readerCount = 0;
isWriting = false;
}
#endregion
#region Public Methods
public void SyncRead(Action action)
{
if (action == null)
{
return;
}
EnterReadLock();
try
{
action();
}
finally
{
ExitReadLock();
}
}
public void SyncWrite(Action action)
{
if (action == null)
{
return;
}
EnterWriteLock();
try
{
action();
}
finally
{
ExitWriteLock();
}
}
public void EnterReadLock()
{
lock (internalLock)
{
while (isWriting)
{
Monitor.Wait(internalLock);
}
++readerCount;
}
}
public void ExitReadLock()
{
lock (internalLock)
{
--readerCount;
Monitor.PulseAll(internalLock);
}
}
public void EnterWriteLock()
{
lock (internalLock)
{
while (isWriting)
{
Monitor.Wait(internalLock);
}
isWriting = true;
while (readerCount > 0)
{
Monitor.Wait(internalLock);
}
}
}
public void ExitWriteLock()
{
lock (internalLock)
{
isWriting = false;
Monitor.PulseAll(internalLock);
}
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment