private T RetrieveClone(Transact transaction) { if (ReferenceEquals(transaction, null)) { return(base.Value); } object value; Volatile.Write(ref _inUse, 1); if (transaction._writeLog.TryGetValue(this, out value)) { return((T)value); } if (transaction._readLog.TryGetValue(this, out value)) { return((T)value); } var original = RetrieveValue(transaction._parentTransaction); var clone = _cloner.Clone(original); if (!_comparer.Equals(clone, original)) { transaction._writeLog.Set(this, clone); } transaction._readLog.TryAdd(this, original); return(clone); }
private T RetrieveValue(Transact transaction) { if (ReferenceEquals(transaction, null)) { return(base.Value); } else { object value; Volatile.Write(ref _inUse, 1); if (transaction._writeLog.TryGetValue(this, out value)) { return((T)value); } if (transaction._readLog.TryGetValue(this, out value)) { return((T)value); } var original = RetrieveValue(transaction._parentTransaction); transaction._readLog.TryAdd(this, original); return(original); } }
public Transact() { _writeLog = new WeakHashBucket<IResource, object, WeakNeedle<IResource>>(); _readLog = new WeakHashBucket<IResource, object, WeakNeedle<IResource>>(); _parentTransaction = _currentTransaction; _currentTransaction = this; }
public Transact() { WriteLog = new ThreadSafeDictionary <IResource, object>(); ReadLog = new ThreadSafeDictionary <IResource, object>(); ParentTransaction = _currentTransaction; _currentTransaction = this; _thread = Thread.CurrentThread; }
public Transact() { _writeLog = new SafeDictionary <IResource, object>(); _readLog = new SafeDictionary <IResource, object>(); _parentTransaction = _currentTransaction; _currentTransaction = this; _thread = Thread.CurrentThread; }
private void StoreValue(Transact transaction, T value) { if (!IsAlive || ReferenceEquals(transaction, null)) { base.Value = value; } else { transaction._writeLog.Set(this, value); } }
private void StoreValue(Transact transaction, T value) { if (!IsAlive || transaction == null) { base.Value = value; } else { Volatile.Write(ref _inUse, 1); transaction.WriteLog.Set(this, value); } }
private void Release(bool dispose) { for (var currentTransaction = _currentTransaction; currentTransaction != null && currentTransaction != this; currentTransaction = currentTransaction.ParentTransaction) { if (dispose) { currentTransaction.Dispose(); } else { currentTransaction.Release(); } } Release(); if (dispose) { _currentTransaction = ParentTransaction; } }
private T RetrieveValue(Transact transaction) { if (transaction == null) { return(base.Value); } Volatile.Write(ref _inUse, 1); if (transaction.WriteLog.TryGetValue(this, out var value)) { return((T)value); } if (transaction.ReadLog.TryGetValue(this, out value)) { return((T)value); } var original = RetrieveValue(transaction.ParentTransaction); transaction.ReadLog.TryAdd(this, original); return(original); }
private void Rollback(bool disposing) { Transact currentTransaction; do { currentTransaction = _currentTransaction; if (ReferenceEquals(currentTransaction, this)) { break; } else { if (disposing) { currentTransaction.Dispose(); } else { currentTransaction.Rollback(false); } } } while (true); Uncapture(); if (disposing) { _readLog.AutoRemoveDeadItems = false; _writeLog.AutoRemoveDeadItems = false; _currentTransaction = _currentTransaction._parentTransaction; } }
public void Transact_RaceCondition() { var handle = new ManualResetEvent(false); int[] count = { 0, 0 }; var needle = Transact.CreateNeedle(5); var winner = 0; Assert.AreEqual(needle.Value, 5); Task.Factory.StartNew ( () => { using (var transact = new Transact()) { Interlocked.Increment(ref count[0]); handle.WaitOne(); needle.Value += 2; if (transact.Commit()) { winner = 1; } Interlocked.Increment(ref count[1]); } } ); Task.Factory.StartNew ( () => { using (var transact = new Transact()) { Interlocked.Increment(ref count[0]); handle.WaitOne(); needle.Value += 5; if (transact.Commit()) { winner = 2; } 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); } // One, the other, or both Trace.WriteLine("Winner: " + winner); Trace.WriteLine("Value: " + needle.Value); Assert.IsTrue((winner == 1 && needle.Value == 7) || (winner == 2 && needle.Value == 10) || (needle.Value == 12)); handle.Close(); }