// (C) 2004 Novell, Inc (http://www.novell.com)
//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System.Collections;
+using System.Runtime.InteropServices;
+using System.Runtime.ConstrainedExecution;
+
namespace System.Threading
{
- public sealed class ReaderWriterLock
+ [ComVisible (true)]
+ public sealed class ReaderWriterLock: CriticalFinalizerObject
{
private int seq_num = 1;
- private int state = 0;
- private int readers = 0;
+ private int state;
+ private int readers;
+ private int writer_lock_owner;
private LockQueue writer_queue;
private Hashtable reader_locks;
- private int writer_lock_owner;
public ReaderWriterLock()
{
writer_queue = new LockQueue (this);
reader_locks = new Hashtable ();
+
+ GC.SuppressFinalize (this);
+ }
+
+ ~ReaderWriterLock ()
+ {
}
public bool IsReaderLockHeld {
+ [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
get {
lock (this) return reader_locks.ContainsKey (Thread.CurrentThreadId);
}
}
public bool IsWriterLockHeld {
+ [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
get {
lock (this) return (state < 0 && Thread.CurrentThreadId == writer_lock_owner);
}
AcquireReaderLock (millisecondsTimeout, 1);
}
- public void AcquireReaderLock (int millisecondsTimeout, int initialLockCount)
+ void AcquireReaderLock (int millisecondsTimeout, int initialLockCount)
{
lock (this) {
if (HasWriterLock ()) {
return;
}
- // Wait if there is a write lock
- readers++;
- try {
- if (state < 0 || !writer_queue.IsEmpty) {
- if (!Monitor.Wait (this, millisecondsTimeout))
- throw new ApplicationException ("Timeout expited");
- }
- }
- finally {
- readers--;
- }
-
object nlocks = reader_locks [Thread.CurrentThreadId];
- if (nlocks == null) {
+ if (nlocks == null)
+ {
+ // Not currently holding a reader lock
+ // Wait if there is a write lock
+ readers++;
+ try {
+ if (state < 0 || !writer_queue.IsEmpty) {
+ do {
+ if (!Monitor.Wait (this, millisecondsTimeout))
+ throw new ApplicationException ("Timeout expired");
+ } while (state < 0);
+ }
+ }
+ finally {
+ readers--;
+ }
+
reader_locks [Thread.CurrentThreadId] = initialLockCount;
state += initialLockCount;
}
public void AcquireReaderLock(TimeSpan timeout)
{
int ms = CheckTimeout (timeout);
- AcquireReaderLock ((int) timeout.TotalMilliseconds, 1);
+ AcquireReaderLock (ms, 1);
}
public void AcquireWriterLock (int millisecondsTimeout)
state--;
return;
}
- if (state != 0) { // wait while there are reader locks or another writer lock
- if (!writer_queue.Wait (millisecondsTimeout))
- throw new ApplicationException ("Timeout expited");
+
+ // wait while there are reader locks or another writer lock, or
+ // other threads waiting for the writer lock
+ if (state != 0 || !writer_queue.IsEmpty) {
+ do {
+ if (!writer_queue.Wait (millisecondsTimeout))
+ throw new ApplicationException ("Timeout expired");
+ } while (state != 0);
}
state = -initialLockCount;
lock (this) {
if (!HasWriterLock())
throw new ApplicationException ("The thread does not have the writer lock.");
-
- state = lockCookie.ReaderLocks;
- reader_locks [Thread.CurrentThreadId] = state;
- Monitor.Pulse (this);
+
+ if (lockCookie.WriterLocks != 0)
+ state++;
+ else {
+ state = lockCookie.ReaderLocks;
+ reader_locks [Thread.CurrentThreadId] = state;
+ if (readers > 0) {
+ Monitor.PulseAll (this);
+ }
+ }
// MSDN: A thread does not block when downgrading from the writer lock,
// even if other threads are waiting for the writer lock
return cookie;
}
+ [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
public void ReleaseReaderLock()
{
lock (this) {
return;
}
}
+
throw new ApplicationException ("The thread does not have any reader or writer locks.");
}
}
writer_queue.Pulse ();
}
+ [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
public void ReleaseWriterLock()
{
lock (this) {
{
state += releaseCount;
if (state == 0) {
- if (readers > 0)
- Monitor.Pulse (this);
+ if (readers > 0) {
+ Monitor.PulseAll (this);
+ }
else if (!writer_queue.IsEmpty)
writer_queue.Pulse ();
}
LockCookie cookie;
lock (this) {
cookie = GetLockCookie ();
- if (cookie.WriterLocks != 0) return cookie;
+ if (cookie.WriterLocks != 0) {
+ state--;
+ return cookie;
+ }
if (cookie.ReaderLocks != 0)
ReleaseReaderLock (cookie.ReaderLocks, cookie.ReaderLocks);
return cookie;
}
- public bool HasWriterLock ()
+ bool HasWriterLock ()
{
return (state < 0 && Thread.CurrentThreadId == writer_lock_owner);
}