module Concurrent

def atomically

end
b.value += 10
a.value -= 10
Concurrent::atomically do

b = new TVar(100)
a = new TVar(100_000)
@example

Transactions within transactions are flattened to a single transaction.

the transaction. Creating a thread counts as a side-effect.
* If you create a new thread within an atomically, it will not be part of

* It is undefined behaviour to use callcc or Fiber with atomically.

* If an exception escapes an atomically block it will abort the transaction.

side-effects, except for via TVar.
more than once. In most cases your code should be free of
* Most importantly, the block that you pass to atomically may be executed

There are some very important and unusual semantics that you must be aware of:

properties from database transactions.
transactions never interfere with each other. You may recognise these
objects involved will never enter an illegal state, and isolated, in that
that it either happens or it does not, consistent, in that the `TVar`
With respect to the value of `TVar` objects, the transaction is atomic, in
Run a block that reads and writes `TVar`s as a single atomic transaction.
def atomically
  raise ArgumentError.new('no block given') unless block_given?
  # Get the current transaction
  transaction = Transaction::current
  # Are we not already in a transaction (not nested)?
  if transaction.nil?
    # New transaction
    begin
      # Retry loop
      loop do
        # Create a new transaction
        transaction = Transaction.new
        Transaction::current = transaction
        # Run the block, aborting on exceptions
        begin
          result = yield
        rescue Transaction::AbortError => e
          transaction.abort
          result = Transaction::ABORTED
        rescue Transaction::LeaveError => e
          transaction.abort
          break result
        rescue => e
          transaction.abort
          raise e
        end
        # If we can commit, break out of the loop
        if result != Transaction::ABORTED
          if transaction.commit
            break result
          end
        end
      end
    ensure
      # Clear the current transaction
      Transaction::current = nil
    end
  else
    # Nested transaction - flatten it and just run the block
    yield
  end
end