public TransactionInformation(ITransaction transaction, TKey key, TValue originalValue, bool exists, TestReliableDictionary <TKey, TValue> owner)
            {
                _lock         = new object();
                _key          = key;
                _owner        = owner;
                Exists        = exists;
                OriginalValue = originalValue;
                _transaction  = transaction as TestTransaction;
                if (_transaction == null)
                {
                    throw new InvalidOperationException("Incompatible transaction");
                }

                RegisterTransaction();
            }
 private void OnCompletedNoCheck(bool committed)
 {
     lock (_syncLock)
     {
         if (committed)
         {
             _internalQueue = _txQueue;
         }
         while (_waiters.Count > 0)
         {
             var waiter = _waiters.Dequeue();
             Task.Run(() => waiter.TrySetResult(null));
         }
         _waiters.Clear();
         _currentTransaction = null;
     }
 }
        public ITransaction CreateTransaction()
        {
            var transaction = new TestTransaction();

            void OnTransactionOnCompleted(bool completed)
            {
                transaction.Completed -= OnTransactionOnCompleted;

                if (completed)
                {
                    OnTransactionChanged(new NotifyTransactionChangedEventArgs(transaction, NotifyTransactionChangedAction.Commit));
                }
            }

            transaction.Completed += OnTransactionOnCompleted;

            return(transaction);
        }
        private async Task WaitAsync(ITransaction tx, TimeSpan timeout, Task antecedent = null)
        {
            if (antecedent != null)
            {
                await antecedent.ConfigureAwait(false);
            }

            lock (_syncLock)
            {
                if (_currentTransaction == null)
                {
                    _txCompleted        = false;
                    _currentTransaction = tx as TestTransaction;
                    if (_currentTransaction == null)
                    {
                        throw new InvalidOperationException("Incompatible transaction");
                    }

                    _txQueue = new ConcurrentQueue <T>(_internalQueue);
                    _currentTransaction.Completed += OnCompleted;
                    if (_currentTransaction.Result != null)
                    {
                        _txCompleted = true;
                        OnCompletedNoCheck(_currentTransaction.Result.Value);
                    }
                    return;
                }

                if (_currentTransaction.TransactionId == tx.TransactionId)
                {
                    return;
                }

                var tcs = new TaskCompletionSource <object>();
                var cts = new CancellationTokenSource();
                cts.Token.Register(() => tcs.TrySetException(new TimeoutException()));
                _waiters.Enqueue(tcs);
                antecedent = tcs.Task;
                cts.CancelAfter(timeout);
            }

            await WaitAsync(tx, timeout, antecedent).ConfigureAwait(false);
        }