class Concurrent::Transaction
def self.current
def self.current Thread.current[:current_tvar_transaction] end
def self.current=(transaction)
def self.current=(transaction) Thread.current[:current_tvar_transaction] = transaction end
def abort
def abort unlock end
def commit
def commit return false unless valid? @write_log.each_pair do |tvar, value| tvar.unsafe_value = value tvar.unsafe_increment_version end unlock true end
def initialize
def initialize @read_log = [] @write_log = {} end
def read(tvar)
def read(tvar) Concurrent::abort_transaction unless valid? if @write_log.has_key? tvar @write_log[tvar] else @read_log.push(ReadLogEntry.new(tvar, tvar.unsafe_version)) tvar.unsafe_value end end
def unlock
def unlock @write_log.each_key do |tvar| tvar.unsafe_lock.unlock end end
def valid?
def valid? @read_log.each do |log_entry| unless @write_log.has_key? 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_log.has_key? tvar # Try to lock the TVar unless tvar.unsafe_lock.try_lock # Someone else is writing to this TVar - abort Concurrent::abort_transaction end # 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 value written @write_log[tvar] = value end