public void ExceptionPassedOn()
 {
     var variable = new TV<int>();
     TransactionManager.Run(() =>
     {
         variable.Value = 42;
         throw new InvalidCastException("exception thrown inside transaction");
     });
 }
 public void HostChangesAreVisible()
 {
     var variable = new TV<int>(0);
     int actual = TransactionManager.Run(() =>
     {
         variable.Value = 42;
         return TransactionManager.Run(() =>
         {
             return variable.Value;
         });
     });
     Assert.AreEqual(42, actual);
 }
예제 #3
0
        public void BankAccounts()
        {
            var vars = new TV<long>[]{
                new TV<long>(), new TV<long>(), new TV<long>(), new TV<long>()
            };

            Random random = new Random();
            int threadCount = 20;
            Thread[] threads = new Thread[threadCount];
            for (int t = 0; t < threadCount; t++) threads[t] = new Thread(
                (object r) =>
                {
                    Random rand = (Random)r;

                    for (int i = 0; i < 1E3; i++)
                    {
                        int i1 = 0;
                        int i2 = 0;
                        while (i1 == i2)
                        {
                            i1 = rand.Next(4);
                            i2 = rand.Next(4);
                        }
                        int value = rand.Next(10);
                        TransactionManager.Run(() =>
                        {
                            long randVar1Start = vars[i1].Value;
                            long randVar2Start = vars[i2].Value;
                            long randVar1After = randVar1Start + value;
                            long randVar2After = randVar2Start - value;
                            vars[i1].Value = randVar1After;
                            vars[i2].Value = randVar2After;
                            return 0;
                        });
                    }
                }
            );

            foreach (var t in threads) t.Start(new Random(random.Next()));
            foreach (var t in threads) t.Join();

            long sum = TransactionManager.Run(() =>
            {
                return vars.Select(v => v.Value).Sum();
            });

            Assert.AreEqual(0, sum);
        }
 public void WriteRead()
 {
     var variable = new TV<int>();
     int actual = TransactionManager.Run(() =>
     {
         variable.Value = 42;
         return variable.Value;
     });
     Assert.AreEqual(42, actual);
 }
 public void TransactionCloses()
 {
     var variable = new TV<int>(42);
     TransactionManager.Run(() => variable.Value);
     Assert.IsFalse(TransactionManager.TransactionRunning);
 }
 public void TransactionRunningTrue()
 {
     var variable = new TV<int>(42);
     bool wasRunningInTransaction = TransactionManager.Run(() =>
     {
         return TransactionManager.TransactionRunning;
     });
     Assert.IsTrue(wasRunningInTransaction);
 }
 public void ReadWithoutTransaction()
 {
     var variable = new TV<int>(42);
     int dummy = variable.Value;
 }
        public void RollbackOnException()
        {
            var variable = new TV<int>();
            try
            {
                TransactionManager.Run(() =>
                {
                    variable.Value = 42;
                    throw new Exception("exception thrown inside transaction");
                });
            }
            catch (Exception) { }

            int actual = TransactionManager.Run(() => variable.Value);
            Assert.AreEqual(0, actual);
        }
 public void RWRWWrite()
 {
     var variable = new TV<int>(0);
     TransactionManager.Run(() =>
     {
         TransactionManager.Run(() =>
         {
             variable.Value = 42;
         });
     });
     int actual = TransactionManager.Run(() => variable.Value);
     Assert.AreEqual(42, actual);
 }
        public void ReadWriteWithinReadOnlyWithinReadWrite()
        {
            var variable = new TV<int>(42);

            TransactionManager.Run(() =>
            {
                var actual = TransactionManager.RunReadOnly(() =>
                {
                    return TransactionManager.Run(() =>
                    {
                        return variable.Value;
                    });
                });
            });
        }
 public void RollbackedChangesAreInvisible()
 {
     var variable = new TV<int>(0);
     int actual = TransactionManager.Run(() =>
     {
         try
         {
             TransactionManager.Run(() =>
             {
                 variable.Value = 42;
                 throw new InvalidCastException("within nested transaction");
             });
         }
         catch (InvalidCastException) { }
         return variable.Value;
     });
     Assert.AreEqual(0, actual);
 }
예제 #12
0
        /// <summary>
        /// Reads the value of a variable.
        /// </summary>
        /// <param name="variable">Variable to read from.</param>
        /// <returns>Value of the variable.</returns>
        /// <exception cref="OutsideOfTransactionException">Thrown if no transaction is running.</exception>
        /// <exception cref="ConflictException">Thrown if a conflict is detected. 
        /// The transaction and all its host transactions must be roll-backed immediately. The outermost transaction
        /// may then be restarted.
        /// </exception>
        /// <remarks>
        /// ACID properties are guarnateed.
        /// </remarks>
        public object Read(TV variable)
        {
            if (_nestedTransactions <= 0) throw new OutsideOfTransactionException(ExceptionMessages.InternalError);

            // Read the variable, ensure that it is not changed or locked by spinning.
            object value;
            long preVLock;
            long postVLock;
            do
            {
                preVLock = Interlocked.Read(ref variable.__vLock);
                value = variable.__Value;
                postVLock = Interlocked.Read(ref variable.__vLock);
            } while (preVLock != postVLock || TransactionManager.IsLocked(preVLock));

            // abort if another thread has written to it since our transaction started
            if (preVLock > _readVersion) throw new ConflictException();

            return value;
        }
 public void ValidationSuccess()
 {
     var variable = new TV<int>(0);
     variable.Validation += (sender, e) => { };
     TransactionManager.Run(() =>
     {
         variable.Value = 1;
     });
     int actual = TransactionManager.Run(() => variable.Value);
     Assert.AreEqual(1, actual);
 }
 public void WriteWithinNestedReadOnly()
 {
     var variable = new TV<int>(42);
     TransactionManager.Run(() =>
     {
         return TransactionManager.RunReadOnly(() =>
         {
             variable.Value = 42;
             return 0;
         });
     });
 }
 public void ValidationInTransaction()
 {
     var variable = new TV<int>(0);
     variable.Validation += (sender, e) => { Assert.IsTrue(TransactionManager.TransactionRunning); };
     TransactionManager.Run(() =>
     {
         variable.Value = 1;
     });
 }
 public void ValidationFailureRollback()
 {
     var variable = new TV<int>(0);
     variable.Validation += (sender, e) => e.Cancel = true;
     try
     {
         TransactionManager.Run(() =>
         {
             variable.Value = 1;
         });
     }
     catch { }
     int actual = TransactionManager.Run(() => variable.Value);
     Assert.AreEqual(0, actual);
 }
 public void ValidationFails()
 {
     var variable = new TV<int>(0);
     variable.Validation += (sender, e) => e.Cancel = true;
     TransactionManager.Run(() =>
     {
         variable.Value = 1;
     });
 }
 public void WriteTwo()
 {
     var variableA = new TV<int>();
     var variableB = new TV<int>();
     TransactionManager.Run(() =>
     {
         variableA.Value = 42;
         variableB.Value = 43;
     });
     int actualA = TransactionManager.Run(() => variableA.Value);
     int actualB = TransactionManager.Run(() => variableB.Value);
     Assert.AreEqual(42, actualA);
     Assert.AreEqual(43, actualB);
 }
예제 #19
0
        public void Serializability()
        {
            var variableA = new TV<int>();
            var variableB = new TV<int>();

            Thread t1 = new Thread(() =>
            {
                TransactionManager.Run(() =>
                {
                    variableA.Value = 10;
                    Thread.Sleep(20);
                    variableB.Value = 11;
                });
            });

            Thread t2 = new Thread(() =>
            {
                TransactionManager.Run(() =>
                {
                    variableA.Value = 20;
                    Thread.Sleep(20);
                    variableB.Value = 21;
                });
            });

            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();

            int actual = TransactionManager.Run(() =>
            {
                return variableB.Value - variableA.Value;
            });

            Assert.AreEqual(1, actual);
        }
 public void WriteWithoutTransaction()
 {
     var variable = new TV<int>();
     variable.Value = 42;
 }
 public void RWRWRead()
 {
     var variable = new TV<int>(42);
     var actual = TransactionManager.Run(() =>
     {
         return TransactionManager.Run(() =>
         {
             return variable.Value;
         });
     });
     Assert.AreEqual(42, actual);
 }
 public void Read()
 {
     var variable = new TV<int>(42);
     int actual = TransactionManager.Run(() => variable.Value);
     Assert.AreEqual(42, actual);
 }
 public void PropertyChangedOutsideTransaction()
 {
     var variable = new TV<int>(0);
     variable.PropertyChanged += (sender, e) => { Assert.IsFalse(TransactionManager.TransactionRunning); };
     TransactionManager.Run(() =>
     {
         variable.Value = 1;
     });
 }
예제 #24
0
 /// <summary>
 /// Writes a value into a variable.
 /// </summary>
 /// <param name="variable">Variable to write to.</param>
 /// <param name="value">Value to store in the variable.</param>
 /// <exception cref="OutsideOfTransactionException">Thrown if no transaction is running.</exception>
 /// <exception cref="ReadOnlyTransactionException">Thrown if called within a read-only transaction.</exception>
 /// <remarks>
 /// This method always throws an exception. Either a <c>OutsideOfTransactionException</c> if no
 /// transaction is running, or a <c>ReadOnlyTransactionException</c> if one is running (since all transactions
 /// used with this strategy are read-only.
 /// </remarks>
 public void Write(TV variable, object value)
 {
     if (_nestedTransactions <= 0) throw new OutsideOfTransactionException(ExceptionMessages.InternalError);
     throw new ReadOnlyTransactionException(ExceptionMessages.WriteInReadonlyTransaction);
 }
 public void ReadOnlyWrite()
 {
     var variable = new TV<int>(0);
     TransactionManager.RunReadOnly(() =>
     {
         variable.Value = 42;
         return 0;
     });
 }
 public void ReadTwo()
 {
     var variableA = new TV<int>(42);
     var variableB = new TV<int>(43);
     int actual = TransactionManager.Run(() => variableB.Value - variableA.Value);
     Assert.AreEqual(1, actual);
 }
 public void PropertyChangedRaised()
 {
     int called = 0;
     var variable = new TV<int>(0);
     variable.PropertyChanged += (sender, e) => called++;
     TransactionManager.Run(() =>
     {
         variable.Value = 1;
     });
     Assert.AreEqual(1, called);
 }