Commits

Anonymous committed 0c7ca3e Draft

added timed versions of Acquire* to Lightswitch, ReaderWriterLock and
ReaderWriterUpdateLock

Comments (0)

Files changed (3)

Cineraria.Concurrency/Lightswitch.cs

 namespace Cineraria.Concurrency
 {
     /// <summary>
-    /// Acquires the specified semaphore on first acquire and releases it on last release.
+    /// Acquires the specified semaphore on first acquire and releases it on
+    /// last release.
     /// </summary>
-    public class Lightswitch : ISync
+    public class Lightswitch : ITimedSync
     {
         /// <summary>
         /// Object used for lock() blocks.
         /// <summary>
         /// The <see cref="ISync"/> object being "switched on and off".
         /// </summary>
-        private readonly ISync _innerPermission;
+        private readonly ITimedSync _innerPermission;
 
         /// <summary>
-        /// The number of threads that have acquired this <see cref="Lightswitch"/>.
+        /// The number of threads that have acquired this
+        /// <see cref="Lightswitch"/>.
         /// </summary>
         private int _count = 0;
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="Lightswitch"/> class with the specified
-        /// inner permission.
+        /// Initializes a new instance of the <see cref="Lightswitch"/> class
+        /// with the specified inner permission.
         /// </summary>
         /// <param name="innerPermission">The inner permission.</param>
-        public Lightswitch(ISync innerPermission)
+        public Lightswitch(ITimedSync innerPermission)
         {
             this._innerPermission = innerPermission;
         }
 
         /// <summary>
-        /// Acquires a logical token. Will acquire inner permission if no other tokens
+        /// Acquires a logical token. Will acquire inner permission if no other
+        /// tokens have been acquired.
+        /// </summary>
+        public void Acquire()
+        {
+            this.Acquire(-1);
+        }
+
+        /// <summary>
+        /// Waits a maximum of <paramref name="milliseconds"/> to acquire a
+        /// logical token. Will acquire inner permission if no other tokens
         /// have been acquired.
         /// </summary>
-        public void Acquire()
+        /// <param name="milliseconds">
+        /// The maximum number of milliseconds to wait.
+        /// </param>
+        /// <returns>
+        /// true if a logical token was acquired, false otherwise.
+        /// </returns>
+        public bool Acquire(int milliseconds)
         {
             lock (this._syncRoot)
             {
                 if (this._count == 0)
                 {
-                    this._innerPermission.Acquire();
+                    if (!this._innerPermission.Acquire(milliseconds))
+                    {
+                        return false;
+                    }
                 }
 
                 this._count++;
             }
+
+            return true;
         }
 
         /// <summary>
-        /// Releases a logical token. Will release inner permission if all other tokens
-        /// have been released.
+        /// Releases a logical token. Will release inner permission if all
+        /// other tokens have been released.
         /// </summary>
         public void Release()
         {

Cineraria.Concurrency/ReaderWriterLock.cs

         internal readonly Lightswitch ReadPermission;
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="ReaderWriterLock"/> class.
+        /// Initializes a new instance of the <see cref="ReaderWriterLock"/>
+        /// class.
         /// </summary>
         public ReaderWriterLock()
         {
         /// </summary>
         public void AcquireReader()
         {
-            this.Turnstile.Acquire();
+            this.AcquireReader(-1);
+        }
+
+        /// <summary>
+        /// Waits a maximum of <paramref name="milliseconds"/> to acquire
+        /// permission to read.
+        /// </summary>
+        /// <param name="milliseconds">
+        /// The maximum number of milliseconds to wait.
+        /// </param>
+        /// <returns>
+        /// true if a permission was acquired, false otherwise.
+        /// </returns>
+        public bool AcquireReader(int milliseconds)
+        {
+            if (!this.Turnstile.Acquire(milliseconds))
+            {
+                return false;
+            }
+
             this.Turnstile.Release();
+
+            // Don't have to attempt here because it is guaranteed that no
+            // other thread is attempting to acquire WritePermission.
             this.ReadPermission.Acquire();
+            return true;
         }
 
         /// <summary>
         /// </summary>
         public void AcquireWriter()
         {
-            this.Turnstile.Acquire();
+            this.AcquireWriter(-1);
+        }
+
+        /// <summary>
+        /// Waits a maximum of <paramref name="milliseconds"/> to acquire
+        /// permission to write.
+        /// </summary>
+        /// <param name="milliseconds">
+        /// The maximum number of milliseconds to wait.
+        /// </param>
+        /// <returns>
+        /// true if a permission was acquired, false otherwise.
+        /// </returns>
+        public bool AcquireWriter(int milliseconds)
+        {
+            if (!this.Turnstile.Acquire(milliseconds))
+            {
+                return false;
+            }
+
+            // Don't have to attempt here because it is guaranteed that no
+            // other thread is attempting to acquire WritePermission.
             this.WritePermission.Acquire();
+            return true;
         }
 
         /// <summary>

Cineraria.Concurrency/ReaderWriterUpdateLock.cs

         /// A semaphore representing permission to block writers for a
         /// potential update.
         /// </summary>
-        private readonly Semaphore _updatePermission = new Mutex(1);
+        private readonly Mutex _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();
+            this.AcquireUpdate(-1);
+        }
+
+        /// <summary>
+        /// Waits a maximum of <paramref name="milliseconds"/> to acquire a
+        /// block on all writers for a potential update.
+        /// </summary>
+        /// <param name="milliseconds">
+        /// The maximum number of milliseconds to wait for acquisition.
+        /// </param>
+        /// <returns>true if block was acquired, false otherwise.</returns>
+        public bool AcquireUpdate(int milliseconds)
+        {
+            if (!this._updatePermission.Acquire(milliseconds))
+            {
+                return false;
+            }
+
+            if (!this.ReadPermission.Acquire(milliseconds))
+            {
+                this._updatePermission.Release();
+                return false;
+            }
+
+            return true;
         }
 
         /// <summary>
         /// </summary>
         public void PromoteUpdate()
         {
-            this.Turnstile.Acquire();
+            this.PromoteUpdate(-1);
+        }
 
-            // Since AcquireWriter acquires turnstile before writePermission,
-            // readPermission can be released here without a writer potentially
-            // acqiring writePermission before this thread.
+        /// <summary>
+        /// Waits a maximum of <paramref name="milliseconds"/> to promote an
+        /// update block to write permission. Guaranteed to not be preempted by
+        /// another write permission request. On failure, caller retains update
+        /// block.
+        /// </summary>
+        /// <param name="milliseconds">
+        /// The maximum number of milliseconds to wait for promotion.
+        /// </param>
+        /// <returns>
+        /// true if promotion was successful, false otherwise.
+        /// </returns>
+        public bool PromoteUpdate(int milliseconds)
+        {
+            if (!this.Turnstile.Acquire(milliseconds))
+            {
+                return false;
+            }
+
+            // Since AcquireWriter acquires turnstile before WritePermission,
+            // ReadPermission can be released here without a writer potentially
+            // acqiring WritePermission before this thread.
             this.ReadPermission.Release();
+
+            // Don't have to attempt here because it is guaranteed that no
+            // other thread is attempting to acquire WritePermission.
             this.WritePermission.Acquire();
             this._updatePermission.Release();
+            return true;
         }
 
         /// <summary>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.