# Class: Concurrent::Transaction

Inherits:
  Object
  - Object
  - Concurrent::Transaction
  show all

Defined in:
  lib/concurrent-ruby/concurrent/tvar.rb

## Defined Under Namespace

Classes: ReadLogEntry

## Constant Summary collapse

ABORTED =

      ::Object.new

AbortError =

      Class.new(StandardError)

LeaveError =

      Class.new(StandardError)

## Class Method Summary collapse

- .current ⇒ undocumented
- .current=(transaction) ⇒ undocumented

## Instance Method Summary collapse

- #abort ⇒ undocumented
- #commit ⇒ undocumented
- #initialize ⇒ Transaction constructor

  A new instance of Transaction.

- #read(tvar) ⇒ undocumented
- #unlock ⇒ undocumented
- #valid? ⇒ Boolean
- #write(tvar, value) ⇒ undocumented

## Constructor Details

### #initialize ⇒ `Transaction`

Returns a new instance of Transaction.

    172
    173
    174
    175

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 172

    def initialize
      @read_log  = []
      @write_log = {}
    end

## Class Method Details

### .current ⇒ `undocumented`

    248
    249
    250

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 248

    def self.current
      Thread.current[:current_tvar_transaction]
    end

### .current=(transaction) ⇒ `undocumented`

    252
    253
    254

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 252

    def self.current=(transaction)
      Thread.current[:current_tvar_transaction] = transaction
    end

## Instance Method Details

### #abort ⇒ `undocumented`

    213
    214
    215

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 213

    def abort
      unlock
    end

### #commit ⇒ `undocumented`

    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 217

    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

### #read(tvar) ⇒ `undocumented`

    177
    178
    179
    180
    181
    182
    183
    184
    185
    186

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 177

    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

### #unlock ⇒ `undocumented`

    242
    243
    244
    245
    246

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 242

    def unlock
      @write_log.each_key do |tvar|
        tvar.unsafe_lock.unlock
      end
    end

### #valid? ⇒ `Boolean`

Returns:

- (`Boolean`)

    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 230

    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

### #write(tvar, value) ⇒ `undocumented`

    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211

    # File 'lib/concurrent-ruby/concurrent/tvar.rb', line 188

    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