public void NestedTransactionAndRollback() { var needleA = Transact.CreateNeedle(5); var needleB = Transact.CreateNeedle(1); var thread = new Thread(() => { using (var transaction = new Transact()) { needleB.Value = 2; transaction.Commit(); using (var transact = new Transact()) { needleA.Value = 9; Assert.AreEqual(9, needleA.Value); Assert.AreEqual(2, needleB.Value); transact.Commit(); } Assert.AreEqual(9, needleA.Value); Assert.AreEqual(2, needleB.Value); transaction.Rollback(); Assert.AreEqual(5, needleA.Value); Assert.AreEqual(2, needleB.Value); using (new Transact()) { needleA.Value = 13; Assert.AreEqual(13, needleA.Value); Assert.AreEqual(2, needleB.Value); transaction.Rollback(); Assert.AreEqual(5, needleA.Value); Assert.AreEqual(2, needleB.Value); } needleA.Value = 15; transaction.Commit(); } }); thread.Start(); thread.Join(); Assert.AreEqual(15, needleA.Value); Assert.AreEqual(2, needleB.Value); }
public void ReadonlyTransaction() // TODO: Review { using (var handle = new ManualResetEvent(false)) { int[] count = { 0, 0 }; var needle = Transact.CreateNeedle(5); Assert.AreEqual(needle.Value, 5); ThreadPool.QueueUserWorkItem ( _ => { using (var transact = new Transact()) { Interlocked.Increment(ref count[0]); handle.WaitOne(); // This one only reads GC.KeepAlive(needle.Value); transact.Commit(); Interlocked.Increment(ref count[1]); } } ); ThreadPool.QueueUserWorkItem ( _ => { using (var transact = new Transact()) { Interlocked.Increment(ref count[0]); handle.WaitOne(); needle.Value += 5; transact.Commit(); Interlocked.Increment(ref count[1]); } } ); while (Thread.VolatileRead(ref count[0]) != 2) { Thread.Sleep(0); } handle.Set(); while (Thread.VolatileRead(ref count[1]) != 2) { Thread.Sleep(0); } // There is no reason for failure Assert.IsTrue(needle.Value == 10); handle.Close(); } }
public void NoRaceCondition() // TODO: Review { using (var handle = new ManualResetEvent(false)) { int[] count = { 0, 0 }; var needleA = Transact.CreateNeedle(5); var needleB = Transact.CreateNeedle(5); Assert.AreEqual(needleA.Value, 5); Assert.AreEqual(needleB.Value, 5); ThreadPool.QueueUserWorkItem ( _ => { using (var transact = new Transact()) { Interlocked.Increment(ref count[0]); handle.WaitOne(); needleA.Value += 2; transact.Commit(); } Interlocked.Increment(ref count[1]); } ); ThreadPool.QueueUserWorkItem ( _ => { using (var transact = new Transact()) { Interlocked.Increment(ref count[0]); handle.WaitOne(); needleB.Value += 5; transact.Commit(); } Interlocked.Increment(ref count[1]); } ); global::Theraot.Threading.ThreadingHelper.SpinWaitUntil(ref count[0], 2); handle.Set(); global::Theraot.Threading.ThreadingHelper.SpinWaitUntil(ref count[1], 2); // Both Assert.AreEqual(7, needleA.Value); Assert.AreEqual(10, needleB.Value); handle.Close(); } }
public void Rollback() { var needleA = Transact.CreateNeedle(5); var needleB = Transact.CreateNeedle(5); try { using (var transact = new Transact()) { const int Movement = 2; needleA.Value += Movement; ThrowException(); // Really, it is evident this code will not run needleB.Value -= Movement; transact.Commit(); } } catch (Exception exception) { // Catch'em all GC.KeepAlive(exception); } // We did not commit Assert.AreEqual(5, needleA.Value); Assert.AreEqual(5, needleB.Value); //--- using (var transact = new Transact()) { needleA.Value = 9; Assert.AreEqual(9, needleA.Value); Assert.AreEqual(5, needleB.Value); transact.Rollback(); Assert.AreEqual(5, needleA.Value); Assert.AreEqual(5, needleB.Value); } // We did rollback Assert.AreEqual(5, needleA.Value); Assert.AreEqual(5, needleB.Value); using (var transact = new Transact()) { needleA.Value = 9; Assert.AreEqual(9, needleA.Value); Assert.AreEqual(5, needleB.Value); transact.Rollback(); Assert.AreEqual(5, needleA.Value); Assert.AreEqual(5, needleB.Value); needleA.Value = 11; Assert.AreEqual(11, needleA.Value); Assert.AreEqual(5, needleB.Value); transact.Commit(); } // We did rollback and commit again Assert.AreEqual(11, needleA.Value); Assert.AreEqual(5, needleB.Value); }
public void AbsentTransaction() { var needle = Transact.CreateNeedle(5); Assert.AreEqual(5, needle.Value); }