Commits

Anonymous committed 507b684 Draft

added ReaderWriterUpdateLock

Comments (0)

Files changed (3)

Cineraria.Concurrency/Cineraria.Concurrency.csproj

     <Compile Include="ReaderPriorityWriterLock.cs" />
     <Compile Include="ReaderWriterLock.cs" />
     <Compile Include="ReaderWriterPriorityLock.cs" />
+    <Compile Include="ReaderWriterUpdateLock.cs" />
     <Compile Include="Rendezvous.cs" />
     <Compile Include="Semaphore.cs" />
     <Compile Include="StrongSemaphore.cs" />

Cineraria.Concurrency/ReaderWriterLock.cs

         /// <summary>
         /// A semaphore representing permission to read.
         /// </summary>
-        private readonly Semaphore _writePermission = new Semaphore(1);
+        internal readonly Mutex WritePermission = new Mutex(1);
 
         /// <summary>
         /// A turnstile used to give writers and readers equal priority.
         /// </summary>
-        private readonly Semaphore _turnstile = new Semaphore(1);
+        internal readonly Mutex Turnstile = new Mutex(1);
 
         /// <summary>
         /// A lightswitch representing permission to read.
         /// </summary>
-        private readonly Lightswitch _readPermission;
+        internal readonly Lightswitch ReadPermission;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ReaderWriterLock"/> class.
         /// </summary>
         public ReaderWriterLock()
         {
-            this._readPermission = new Lightswitch(this._writePermission);
+            this.ReadPermission = new Lightswitch(this.WritePermission);
         }
 
         /// <summary>
         /// </summary>
         public void AcquireReader()
         {
-            this._turnstile.Acquire();
-            this._turnstile.Release();
-            this._readPermission.Acquire();
+            this.Turnstile.Acquire();
+            this.Turnstile.Release();
+            this.ReadPermission.Acquire();
         }
 
         /// <summary>
         /// </summary>
         public void ReleaseReader()
         {
-            this._readPermission.Release();
+            this.ReadPermission.Release();
         }
 
         /// <summary>
         /// </summary>
         public void AcquireWriter()
         {
-            this._turnstile.Acquire();
-            this._writePermission.Acquire();
+            this.Turnstile.Acquire();
+            this.WritePermission.Acquire();
         }
 
         /// <summary>
         /// </summary>
         public void ReleaseWriter()
         {
-            this._writePermission.Release();
-            this._turnstile.Release();
+            this.WritePermission.Release();
+            this.Turnstile.Release();
         }
     }
 }

Cineraria.Concurrency/ReaderWriterUpdateLock.cs

+// -----------------------------------------------------------------------
+// <copyright file="ReaderWriterUpdateLock.cs">
+//     Copyright (c) Rhys 22/05/2012. All rights reserved.
+// </copyright>
+// -----------------------------------------------------------------------
+
+namespace Cineraria.Concurrency
+{
+    /// <summary>
+    /// A neutral reader/writer/update lock.
+    /// </summary>
+    public class ReaderWriterUpdateLock : ReaderWriterLock
+    {
+        /// <summary>
+        /// A semaphore representing permission to block writers for a
+        /// potential update.
+        /// </summary>
+        private readonly Semaphore _updatePermission = new Mutex(1);
+
+        /// <summary>
+        /// Acquires a block on all writers for a potential update.
+        /// </summary>
+        public void AcquireUpdate()
+        {
+            this._updatePermission.Acquire();
+            this.ReadPermission.Acquire();
+        }
+
+        /// <summary>
+        /// Promotes an update block to write permission. Guaranteed to not be
+        /// preempted by another write permission request.
+        /// </summary>
+        public void PromoteUpdate()
+        {
+            this.Turnstile.Acquire();
+
+            // Since AcquireWriter acquires turnstile before writePermission,
+            // readPermission can be released here without a writer potentially
+            // acqiring writePermission before this thread.
+            this.ReadPermission.Release();
+            this.WritePermission.Acquire();
+            this._updatePermission.Release();
+        }
+
+        /// <summary>
+        /// Releases a block on all writers for a potential update.
+        /// </summary>
+        public void ReleaseUpdate()
+        {
+            this._updatePermission.Release();
+            this.ReadPermission.Release();
+        }
+    }
+}