/// <summary>Adds a command to the write list of this transaction</summary> /// <remarks>Must be called with m_lock taken</remarks> private void AddWriteCommand_NeedsLocking(WriteCommand command) { var commands = new WriteCommand[1]; commands[0] = command; if (!m_writes.GetOrAdd(command.Key, commands, out commands)) { // there is already a command for that key if (command.Type == Operation.Set) { // Set always overwrites everything if (commands.Length == 1) { // reuse the command array commands[0] = command; return; } // overwrite m_writes.SetItem(command.Key, new[] { command }); return; } var last = commands[commands.Length - 1]; if (last.Type == Operation.Set) { // "SET(X) x ATOMIC(op, P)" are merged into "SET(X')" with X' = atomic(op, X, P) Contract.Assert(commands.Length == 1); command = WriteCommand.MergeSetAndAtomicOperation(last, command.Type, command.Value); // update in place commands[commands.Length - 1] = command; return; } if (last.Type == command.Type) { // atomics of the same kind can be merged command = WriteCommand.MergeTwoAtomicOperations(last, command.Value); // update in place commands[commands.Length - 1] = command; return; } // just queue the command at the end Array.Resize <WriteCommand>(ref commands, commands.Length + 1); commands[commands.Length - 1] = command; m_writes.SetItem(command.Key, commands); } }