Generalize ThreadLockState to include recursive count informations and update them...
authorJérémie Laval <jeremie.laval@gmail.com>
Wed, 1 Sep 2010 12:56:11 +0000 (13:56 +0100)
committerJérémie Laval <jeremie.laval@gmail.com>
Wed, 1 Sep 2010 12:56:11 +0000 (13:56 +0100)
mcs/class/System.Core/System.Threading/ReaderWriterLockSlim.cs
mcs/class/System.Core/System.Threading/ReaderWriterLockSlimExtensions.cs
mcs/class/System.Core/System.Threading/ThreadLockState.cs

index 97bace0d13956f5c8dc3b39fab2a1715c150865f..ec0b1d33be462ef3f345002a8e266ba0664f8c86 100644 (file)
@@ -89,18 +89,24 @@ namespace System.Threading {
 
                public bool TryEnterReadLock (int millisecondsTimeout)
                {
-                       if (CheckState (millisecondsTimeout, ThreadLockState.Read))
+                       ThreadLockState ctstate = CurrentThreadState;
+
+                       if (CheckState (millisecondsTimeout, LockState.Read)) {
+                               ctstate.ReaderRecursiveCount++;
                                return true;
+                       }
 
                        // This is downgrading from upgradable, no need for check since
                        // we already have a sort-of read lock that's going to disappear
                        // after user calls ExitUpgradeableReadLock.
                        // Same idea when recursion is allowed and a write thread wants to
                        // go for a Read too.
-                       if (CurrentThreadState.Has (ThreadLockState.Upgradable)
+                       if (CurrentLockState.Has (LockState.Upgradable)
                            || recursionPolicy == LockRecursionPolicy.SupportsRecursion) {
                                Interlocked.Add (ref rwlock, RwRead);
-                               CurrentThreadState = CurrentThreadState ^ ThreadLockState.Read;
+                               ctstate.LockState = ctstate.LockState ^ LockState.Read;
+                               ctstate.ReaderRecursiveCount++;
+
                                return true;
                        }
                        
@@ -114,7 +120,8 @@ namespace System.Threading {
                                }
 
                                if ((Interlocked.Add (ref rwlock, RwRead) & 0x7) == 0) {
-                                       CurrentThreadState = CurrentThreadState ^ ThreadLockState.Read;
+                                       ctstate.LockState ^= LockState.Read;
+                                       ctstate.ReaderRecursiveCount++;
                                        Interlocked.Decrement (ref numReadWaiters);
                                        if (readerDoneEvent.IsSet ())
                                                readerDoneEvent.Reset ();
@@ -137,10 +144,13 @@ namespace System.Threading {
 
                public void ExitReadLock ()
                {
-                       if (!CurrentThreadState.Has (ThreadLockState.Read))
+                       ThreadLockState ctstate = CurrentThreadState;
+
+                       if (!ctstate.LockState.Has (LockState.Read))
                                throw new SynchronizationLockException ("The current thread has not entered the lock in read mode");
 
-                       CurrentThreadState = ThreadLockState.None;
+                       ctstate.LockState = LockState.None;
+                       ctstate.ReaderRecursiveCount--;
                        if (Interlocked.Add (ref rwlock, -RwRead) >> RwReadBit == 0)
                                readerDoneEvent.Set ();
                }
@@ -152,9 +162,13 @@ namespace System.Threading {
                
                public bool TryEnterWriteLock (int millisecondsTimeout)
                {
-                       bool isUpgradable = CurrentThreadState.Has (ThreadLockState.Upgradable);
-                       if (CheckState (millisecondsTimeout, isUpgradable ? ThreadLockState.UpgradedWrite : ThreadLockState.Write))
+                       ThreadLockState ctstate = CurrentThreadState;
+                       bool isUpgradable = ctstate.LockState.Has (LockState.Upgradable);
+
+                       if (CheckState (millisecondsTimeout, isUpgradable ? LockState.UpgradedWrite : LockState.Write)) {
+                               ctstate.WriterRecursiveCount++;
                                return true;
+                       }
 
                        Stopwatch sw = Stopwatch.StartNew ();
                        Interlocked.Increment (ref numWriteWaiters);
@@ -171,7 +185,8 @@ namespace System.Threading {
 
                                if (state <= stateCheck) {
                                        if (Interlocked.CompareExchange (ref rwlock, RwWrite, state) == state) {
-                                               CurrentThreadState = isUpgradable ? ThreadLockState.UpgradedWrite : ThreadLockState.Write;
+                                               ctstate.LockState = isUpgradable ? LockState.UpgradedWrite : LockState.Write;
+                                               ctstate.WriterRecursiveCount++;
                                                Interlocked.Decrement (ref numWriteWaiters);
                                                if (writerDoneEvent.IsSet ())
                                                        writerDoneEvent.Reset ();
@@ -198,10 +213,13 @@ namespace System.Threading {
 
                public void ExitWriteLock ()
                {
-                       if (!CurrentThreadState.Has (ThreadLockState.Write))
+                       ThreadLockState ctstate = CurrentThreadState;
+
+                       if (!ctstate.LockState.Has (LockState.Write))
                                throw new SynchronizationLockException ("The current thread has not entered the lock in write mode");
                        
-                       CurrentThreadState = CurrentThreadState ^ ThreadLockState.Write;
+                       ctstate.LockState ^= LockState.Write;
+                       ctstate.WriterRecursiveCount--;
                        Interlocked.Add (ref rwlock, -RwWrite);
                        writerDoneEvent.Set ();
                }
@@ -217,10 +235,14 @@ namespace System.Threading {
                //
                public bool TryEnterUpgradeableReadLock (int millisecondsTimeout)
                {
-                       if (CheckState (millisecondsTimeout, ThreadLockState.Upgradable))
+                       ThreadLockState ctstate = CurrentThreadState;
+
+                       if (CheckState (millisecondsTimeout, LockState.Upgradable)) {
+                               ctstate.UpgradeableRecursiveCount++;
                                return true;
+                       }
 
-                       if (CurrentThreadState.Has (ThreadLockState.Read))
+                       if (ctstate.LockState.Has (LockState.Read))
                                throw new LockRecursionException ("The current thread has already entered read mode");
 
                        Stopwatch sw = Stopwatch.StartNew ();
@@ -238,8 +260,10 @@ namespace System.Threading {
                        upgradableEvent.Reset ();
 
                        if (TryEnterReadLock (ComputeTimeout (millisecondsTimeout, sw))) {
-                               CurrentThreadState = ThreadLockState.Upgradable;
+                               ctstate.LockState = LockState.Upgradable;
                                Interlocked.Decrement (ref numUpgradeWaiters);
+                               ctstate.ReaderRecursiveCount--;
+                               ctstate.UpgradeableRecursiveCount++;
                                return true;
                        }
 
@@ -258,13 +282,16 @@ namespace System.Threading {
               
                public void ExitUpgradeableReadLock ()
                {
-                       if (!CurrentThreadState.Has (ThreadLockState.Upgradable | ThreadLockState.Read))
+                       ThreadLockState ctstate = CurrentThreadState;
+
+                       if (!ctstate.LockState.Has (LockState.Upgradable | LockState.Read))
                                throw new SynchronizationLockException ("The current thread has not entered the lock in upgradable mode");
                        
                        upgradableTaken.Value = false;
                        upgradableEvent.Set ();
 
-                       CurrentThreadState = CurrentThreadState ^ ThreadLockState.Upgradable;
+                       ctstate.LockState ^= LockState.Upgradable;
+                       ctstate.UpgradeableRecursiveCount--;
                        Interlocked.Add (ref rwlock, -RwRead);
                }
 
@@ -299,19 +326,19 @@ namespace System.Threading {
                
                public int RecursiveReadCount {
                        get {
-                               return IsReadLockHeld ? IsUpgradeableReadLockHeld ? 0 : 1 : 0;
+                               return CurrentThreadState.ReaderRecursiveCount;
                        }
                }
 
                public int RecursiveUpgradeCount {
                        get {
-                               return IsUpgradeableReadLockHeld ? 1 : 0;
+                               return CurrentThreadState.UpgradeableRecursiveCount;
                        }
                }
 
                public int RecursiveWriteCount {
                        get {
-                               return IsWriteLockHeld ? 1 : 0;
+                               return CurrentThreadState.WriterRecursiveCount;
                        }
                }
 
@@ -339,6 +366,15 @@ namespace System.Threading {
                        }
                }
 
+               LockState CurrentLockState {
+                       get {
+                               return CurrentThreadState.LockState;
+                       }
+                       set {
+                               CurrentThreadState.LockState = value;
+                       }
+               }
+
                ThreadLockState CurrentThreadState {
                        get {
                                if (currentThreadState == null)
@@ -346,19 +382,13 @@ namespace System.Threading {
 
                                ThreadLockState state;
                                if (!currentThreadState.TryGetValue (id, out state))
-                                       currentThreadState[id] = state = ThreadLockState.None;
+                                       currentThreadState[id] = state = new ThreadLockState ();
 
                                return state;
                        }
-                       set {
-                               if (currentThreadState == null)
-                                       currentThreadState = new Dictionary<int, ThreadLockState> ();
-
-                               currentThreadState[id] = value;
-                       }
                }
 
-               bool CheckState (int millisecondsTimeout, ThreadLockState validState)
+               bool CheckState (int millisecondsTimeout, LockState validState)
                {
                        if (disposed)
                                throw new ObjectDisposedException ("ReaderWriterLockSlim");
@@ -367,11 +397,11 @@ namespace System.Threading {
                                throw new ArgumentOutOfRangeException ("millisecondsTimeout");
 
                        // Detect and prevent recursion
-                       ThreadLockState ctstate = CurrentThreadState;
+                       LockState ctstate = CurrentLockState;
 
                        if (recursionPolicy == LockRecursionPolicy.NoRecursion)
-                               if ((ctstate != ThreadLockState.None && ctstate != ThreadLockState.Upgradable)
-                                   || (ctstate == ThreadLockState.Upgradable && validState == ThreadLockState.Upgradable))
+                               if ((ctstate != LockState.None && ctstate != LockState.Upgradable)
+                                   || (ctstate == LockState.Upgradable && validState == LockState.Upgradable))
                                        throw new LockRecursionException ("The current thread has already a lock and recursion isn't supported");
 
                        // If we already had right lock state, just return
@@ -383,10 +413,10 @@ namespace System.Threading {
                        return false;
                }
 
-               static void CheckRecursionAuthorization (ThreadLockState ctstate, ThreadLockState desiredState)
+               static void CheckRecursionAuthorization (LockState ctstate, LockState desiredState)
                {
                        // In read mode you can just enter Read recursively
-                       if (ctstate == ThreadLockState.Read)
+                       if (ctstate == LockState.Read)
                                throw new LockRecursionException ();                            
                }
 
index a4761da915280a6872401fbe9d1f28d2e0d3097c..b7d8524c2e47f2279b5b44d6848b00492b03ebd2 100644 (file)
@@ -32,7 +32,7 @@ namespace System.Threading
 {
        internal static class ReaderWriterLockSlimExtensions
        {
-               internal static bool Has (this ThreadLockState state, ThreadLockState value)
+               internal static bool Has (this LockState state, LockState value)
                {
                        return (state & value) > 0;
                }
index 9a5b5f6b0a74d632ba42a3c462a8438f0e4c5154..593261e6e59bc5b2ef272e6cb4e779ecbae32d14 100644 (file)
@@ -31,7 +31,7 @@ using System;
 namespace System.Threading
 {
        [Flags]
-       internal enum ThreadLockState
+       internal enum LockState
        {
                None = 0,
                Read = 1,
@@ -40,4 +40,12 @@ namespace System.Threading
                UpgradedRead = 5,
                UpgradedWrite = 6
        }
+
+       internal class ThreadLockState
+       {
+               public LockState LockState;
+               public int ReaderRecursiveCount;
+               public int WriterRecursiveCount;
+               public int UpgradeableRecursiveCount;
+       }
 }
\ No newline at end of file