« Back to Index

Executing the Clojure STM within JRuby (code modified from “Programming Concurrency on the JVM”)

View original Gist on GitHub

account.rb

$CLASSPATH << "clojure-1.6.0/clojure-1.6.0.jar" # Downloaded from http://clojure.org/downloads

require "java"
java_import "clojure.lang.Ref"
java_import "clojure.lang.LockingTransaction"

class Account
  attr_reader :name

  def initialize(name, initial_balance)
    @name    = name
    @balance = Ref.new initial_balance
  end

  def balance
    @balance.deref
  end

  def deposit(amount)
    LockingTransaction.run_in_transaction do
      if amount > 0
        @balance.set @balance.deref + amount
        p "Deposited $#{amount} into account #{@name}"
      else
        raise "The amount must be greater than zero"
      end
    end
  end

  def withdraw(amount)
    LockingTransaction.run_in_transaction do
      if amount > 0 && @balance.deref >= amount
        @balance.set @balance.deref - amount
      else
        raise "Can't withdraw $#{amount}; balance is $#{@balance.deref}"
      end
    end
  end
end

def transfer(from, to, amount)
  LockingTransaction.run_in_transaction do
    to.deposit amount
    from.withdraw amount
  end
end

def transfer_and_print(from, to, amount)
  begin
    transfer from, to, amount
  rescue StandardError => e
    p "Transfer failed: #{e}"
  end

  p "Balance of 'from' account (#{from.name}) is $#{from.balance}"
  p "Balance of 'to' account (#{to.name}) is $#{to.balance}"
end

account1 = Account.new 1, 2000
account2 = Account.new 2, 100

p "account1 balance is $#{account1.balance}"
p "account2 balance is $#{account2.balance}"
p "---"

transfer_and_print account1, account2, 500
p "---"
transfer_and_print account1, account2, 5000

output.zsh

"account1 balance is $2000"
"account2 balance is $100"
"---"
"Deposited $500 into account 2"
"Balance of 'from' account (1) is $1500"
"Balance of 'to' account (2) is $600"
"---"
"Deposited $5000 into account 2"
"Transfer failed: Can't withdraw $5000; balance is $1500"
"Balance of 'from' account (1) is $1500"
"Balance of 'to' account (2) is $600"