class Concurrent::Transaction

def self.current

def self.current
  CURRENT_TRANSACTION.value
end

def self.current=(transaction)

def self.current=(transaction)
  CURRENT_TRANSACTION.value = transaction
end

def abort

def abort
  @undo_log.each do |entry|
    entry.tvar.unsafe_value = entry.value
  end
  unlock
end

def commit

def commit
  return false unless valid?
  @write_set.each do |tvar|
    tvar.unsafe_increment_version
  end
  unlock
  
  true
end

def initialize

def initialize
  @write_set = Set.new
  @read_log = []
  @undo_log = []
end

def read(tvar)

def read(tvar)
  Concurrent::abort_transaction unless valid?
  @read_log.push(ReadLogEntry.new(tvar, tvar.unsafe_version))
  tvar.unsafe_value
end

def unlock

def unlock
  @write_set.each do |tvar|
    tvar.unsafe_lock.unlock
  end
end

def valid?

def valid?
  @read_log.each do |log_entry|
    unless @write_set.include? log_entry.tvar
      if log_entry.tvar.unsafe_version > log_entry.version
        return false
      end
    end
  end
  true
end

def write(tvar, value)

def write(tvar, value)
  # Have we already written to this TVar?
  unless @write_set.include? tvar
    # Try to lock the TVar
    unless tvar.unsafe_lock.try_lock
      # Someone else is writing to this TVar - abort
      Concurrent::abort_transaction
    end
    # We've locked it - add it to the write set
    @write_set.add(tvar)
    # If we previously wrote to it, check the version hasn't changed
    @read_log.each do |log_entry|
      if log_entry.tvar == tvar and tvar.unsafe_version > log_entry.version
        Concurrent::abort_transaction
      end
    end
  end
  # Record the current value of the TVar so we can undo it later
  @undo_log.push(UndoLogEntry.new(tvar, tvar.unsafe_value))
  # Write the new value to the TVar
  tvar.unsafe_value = value
end