Last active
December 20, 2015 15:19
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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