diff Implab.Test/AsyncTests.cs @ 136:e9e7940c7d98 v2

shared locks + tests
author cin
date Mon, 16 Feb 2015 01:14:09 +0300
parents f803565868a4
children f75cfa58e3d4
line wrap: on
line diff
--- a/Implab.Test/AsyncTests.cs	Fri Feb 13 02:08:01 2015 +0300
+++ b/Implab.Test/AsyncTests.cs	Mon Feb 16 01:14:09 2015 +0300
@@ -774,6 +774,79 @@
                 Assert.IsTrue(pSurvive.Join());
             }
         }
+
+        [TestMethod]
+        public void SharedLockTest() {
+            var l = new SharedLock();
+            int shared = 0;
+            int exclusive = 0;
+            var s1 = new Signal();
+            var log = new AsyncQueue<string>();
+
+            try {
+                AsyncPool.RunThread(
+                    () => {
+                        log.Enqueue("Reader #1 started");
+                        try {
+                            l.LockShared();
+                            log.Enqueue("Reader #1 lock got");
+                            if (Interlocked.Increment(ref shared) == 2)
+                                s1.Set();
+                            s1.Wait();
+                            log.Enqueue("Reader #1 finished");
+                            Interlocked.Decrement(ref shared);
+                        } finally {
+                            l.Release();
+                            log.Enqueue("Reader #1 lock released");
+                        }
+                    },
+                    () => {
+                        log.Enqueue("Reader #2 started");
+
+                        try {
+                            l.LockShared();
+                            log.Enqueue("Reader #2 lock got");
+
+                            if (Interlocked.Increment(ref shared) == 2)
+                                s1.Set();
+                            s1.Wait();
+                            log.Enqueue("Reader #2 upgrading to writer");
+                            Interlocked.Decrement(ref shared);
+                            l.Upgrade();
+                            log.Enqueue("Reader #2 upgraded");
+
+                            Assert.AreEqual(1, Interlocked.Increment(ref exclusive));
+                            Assert.AreEqual(0, shared);
+                            log.Enqueue("Reader #2 finished");
+                            Interlocked.Decrement(ref exclusive);
+                        } finally {
+                            l.Release();
+                            log.Enqueue("Reader #2 lock released");
+                        }
+                    },
+                    () => {
+                        log.Enqueue("Writer #1 started");
+                        try {
+                            l.LockExclusive();
+                            log.Enqueue("Writer #1 got the lock");
+                            Assert.AreEqual(1, Interlocked.Increment(ref exclusive));
+                            Interlocked.Decrement(ref exclusive);
+                            log.Enqueue("Writer #1 is finished");
+                        } finally {
+                            l.Release();
+                            log.Enqueue("Writer #1 lock released");
+                        }
+                    }
+                ).Bundle().Join(1000);
+                log.Enqueue("Done");
+            } catch(Exception error) {
+                log.Enqueue(error.Message);
+                throw;
+            } finally {
+                foreach (var m in log)
+                    Console.WriteLine(m);
+            }
+        }
     }
 }