Class: Concurrent::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/concurrent/tvar.rb

Defined Under Namespace

Classes: ReadLogEntry, UndoLogEntry

Constant Summary collapse

ABORTED =
Object.new
CURRENT_TRANSACTION =
ThreadLocalVar.new(nil)
AbortError =
Class.new(StandardError)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTransaction

Returns a new instance of Transaction.



159
160
161
162
163
# File 'lib/concurrent/tvar.rb', line 159

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

Class Method Details

.currentObject



242
243
244
# File 'lib/concurrent/tvar.rb', line 242

def self.current
  CURRENT_TRANSACTION.value
end

.current=(transaction) ⇒ Object



246
247
248
# File 'lib/concurrent/tvar.rb', line 246

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

Instance Method Details

#abortObject



204
205
206
207
208
209
210
# File 'lib/concurrent/tvar.rb', line 204

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

  unlock
end

#commitObject



212
213
214
215
216
217
218
219
220
221
222
# File 'lib/concurrent/tvar.rb', line 212

def commit
  return false unless valid?

  @write_set.each do |tvar|
    tvar.unsafe_increment_version
  end

  unlock
  
  true
end

#read(tvar) ⇒ Object



165
166
167
168
169
# File 'lib/concurrent/tvar.rb', line 165

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

#unlockObject



236
237
238
239
240
# File 'lib/concurrent/tvar.rb', line 236

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

#valid?Boolean

Returns:

  • (Boolean)


224
225
226
227
228
229
230
231
232
233
234
# File 'lib/concurrent/tvar.rb', line 224

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

#write(tvar, value) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/concurrent/tvar.rb', line 171

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