public void AcquireReadWriteLocks_ReadWrite_Blocks() { var name = Guid.NewGuid().ToString(); using (var sma = new Array<byte>(name, 10)) { using (var smr = new Array<byte>(name)) { // Acquire write lock sma.AcquireWriteLock(); // Should block (and fail to reset write signal) Assert.IsFalse(smr.AcquireReadLock(10)); sma.ReleaseWriteLock(); smr.AcquireReadLock(); // Should block (and fail to reset read signal) Assert.IsFalse(sma.AcquireWriteLock(10)); smr.ReleaseReadLock(); } } }
public void AcquireWriteLock_ReadWrite_LocksCorrectly() { var name = Guid.NewGuid().ToString(); Random r = new Random(); int bufSize = 1024; byte[] data = new byte[bufSize]; byte[] readBuf = new byte[bufSize]; bool readIsFirst = false; bool readBlocked = false; int syncValue = 0; // Fill with random data r.NextBytes(data); using (var sma = new Array<byte>(name, bufSize)) { // Acquire write lock early sma.AcquireWriteLock(); using (var smr = new Array<byte>(name)) { var t1 = Task.Factory.StartNew(() => { if (System.Threading.Interlocked.Exchange(ref syncValue, 1) == 0) readIsFirst = true; // Should block until write lock is released smr.AcquireReadLock(); if (System.Threading.Interlocked.Exchange(ref syncValue, 3) == 4) readBlocked = true; smr.CopyTo(readBuf); smr.ReleaseReadLock(); }); System.Threading.Thread.Sleep(10); var t2 = Task.Factory.StartNew(() => { var val = System.Threading.Interlocked.Exchange(ref syncValue, 2); if (val == 0) readIsFirst = false; else if (val == 3) readBlocked = false; System.Threading.Thread.Sleep(10); sma.Write(data); System.Threading.Interlocked.Exchange(ref syncValue, 4); sma.ReleaseWriteLock(); }); Task.WaitAll(t1, t2); Assert.IsTrue(readIsFirst, "The read thread did not enter first."); Assert.IsTrue(readBlocked, "The read thread did not block."); // Check data was written before read for (var i = 0; i < readBuf.Length; i++) { Assert.AreEqual(data[i], readBuf[i]); } } } }