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
AbortError =
Class.new(StandardError)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTransaction

Returns a new instance of Transaction.



157
158
159
160
161
# File 'lib/concurrent/tvar.rb', line 157

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

Class Method Details

.currentObject



240
241
242
# File 'lib/concurrent/tvar.rb', line 240

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

.current=(transaction) ⇒ Object



244
245
246
# File 'lib/concurrent/tvar.rb', line 244

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

Instance Method Details

#abortObject



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

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

  unlock
end

#commitObject



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

def commit
  return false unless valid?

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

  unlock

  true
end

#read(tvar) ⇒ Object



163
164
165
166
167
# File 'lib/concurrent/tvar.rb', line 163

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

#unlockObject



234
235
236
237
238
# File 'lib/concurrent/tvar.rb', line 234

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

#valid?Boolean

Returns:

  • (Boolean)


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

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



169
170
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
# File 'lib/concurrent/tvar.rb', line 169

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