Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérémie Laval <jeremie.laval@gmail.com>2011-01-11 16:39:29 +0300
committerJérémie Laval <jeremie.laval@gmail.com>2011-01-13 18:38:43 +0300
commit2b17a5fa81fd2461814440d1995d2d5633f89036 (patch)
tree54a38f42ebaac283f0c7587dc547d81b6e317cf3 /mcs/class/Mono.Parallel
parent8ff4c9d48797523fd88357a86e4953fff74cca13 (diff)
Protect RwlSlimmer and add Try equivalent
Diffstat (limited to 'mcs/class/Mono.Parallel')
-rw-r--r--mcs/class/Mono.Parallel/Mono.Threading/ReaderWriterLockSlimmer.cs96
1 files changed, 77 insertions, 19 deletions
diff --git a/mcs/class/Mono.Parallel/Mono.Threading/ReaderWriterLockSlimmer.cs b/mcs/class/Mono.Parallel/Mono.Threading/ReaderWriterLockSlimmer.cs
index edd1183ebf2..7a84d52cb98 100644
--- a/mcs/class/Mono.Parallel/Mono.Threading/ReaderWriterLockSlimmer.cs
+++ b/mcs/class/Mono.Parallel/Mono.Threading/ReaderWriterLockSlimmer.cs
@@ -37,18 +37,42 @@ namespace Mono.Threading
int rwlock;
- public void EnterReadLock ()
+ public void EnterReadLock (ref bool taken)
{
+ if (taken)
+ throw new ArgumentException ("taken", "taken needs to be set to false");
+
SpinWait sw = new SpinWait ();
+ bool cont = true;
+
do {
while ((rwlock & (RwWrite | RwWait)) > 0)
sw.SpinOnce ();
- if ((Interlocked.Add (ref rwlock, RwRead) & (RwWait | RwWait)) == 0)
- return;
+ try {}
+ finally {
+ if ((Interlocked.Add (ref rwlock, RwRead) & (RwWait | RwWait)) == 0) {
+ taken = true;
+ cont = false;
+ } else {
+ Interlocked.Add (ref rwlock, -RwRead);
+ }
+ }
+ } while (cont);
+ }
+
+ public void TryEnterReadLock (ref bool taken)
+ {
+ if (taken)
+ throw new ArgumentException ("taken", "taken needs to be set to false");
- Interlocked.Add (ref rwlock, -RwRead);
- } while (true);
+ try {}
+ finally {
+ if ((Interlocked.Add (ref rwlock, RwRead) & (RwWait | RwWrite)) == 0)
+ taken = true;
+ else
+ Interlocked.Add (ref rwlock, -RwRead);
+ }
}
public void ExitReadLock ()
@@ -56,23 +80,57 @@ namespace Mono.Threading
Interlocked.Add (ref rwlock, -RwRead);
}
- public void EnterWriteLock ()
+ public void EnterWriteLock (ref bool taken)
{
+ if (taken)
+ throw new ArgumentException ("taken", "taken needs to be set to false");
+
SpinWait sw = new SpinWait ();
- do {
- int state = rwlock;
- if (state < RwWrite) {
- if (Interlocked.CompareExchange (ref rwlock, RwWrite, state) == state)
- return;
- state = rwlock;
- }
- // We register our interest in taking the Write lock (if upgradeable it's already done)
- while ((state & RwWait) == 0 && Interlocked.CompareExchange (ref rwlock, state | RwWait, state) != state)
+ int state = rwlock;
+
+ try {
+ do {
state = rwlock;
- // Before falling to sleep
- while (rwlock > RwWait)
- sw.SpinOnce ();
- } while (true);
+ if (state < RwWrite) {
+ try {}
+ finally {
+ if (Interlocked.CompareExchange (ref rwlock, RwWrite, state) == state)
+ taken = true;
+ }
+ if (taken)
+ return;
+
+ state = rwlock;
+ }
+
+ while ((state & RwWait) == 0 && Interlocked.CompareExchange (ref rwlock, state | RwWait, state) != state)
+ state = rwlock;
+
+ while (rwlock > RwWait)
+ sw.SpinOnce ();
+ } while (true);
+ } finally {
+ state = rwlock;
+ if (!taken && (state & RwWait) != 0)
+ Interlocked.CompareExchange (ref rwlock, state - RwWait, state);
+ }
+ }
+
+ public void TryEnterWriteLock (ref bool taken)
+ {
+ if (taken)
+ throw new ArgumentException ("taken", "taken needs to be set to false");
+
+ int state = rwlock;
+
+ if (state >= RwWrite)
+ return;
+
+ try {}
+ finally {
+ if (Interlocked.CompareExchange (ref rwlock, RwWrite, state) == state)
+ taken = true;
+ }
}
public void ExitWriteLock ()