Skip to content

Instantly share code, notes, and snippets.

@stuartsierra
Created July 13, 2011 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save stuartsierra/1080607 to your computer and use it in GitHub Desktop.
Save stuartsierra/1080607 to your computer and use it in GitHub Desktop.
Accounts concurrency example in Clojure
;; An example of the "accounts" program for Venkat Subramaniam's
;; Programming Concurrency Workshop, part 1
;;
;; Original Java code by Venkat Subramaniam (@venkat_s)
;; available at http://www.agiledeveloper.com/downloads.html
;; under "Workshop: Programming Concurrency"
;;
;; This code example by Stuart Sierra (@stuartsierra)
;;
;; Überconf 2011, Denver, Colorado
;; July 13, 2011
;;
;; To run this code:
;; Download Clojure from http://clojure.org/
;; Run `java -jar clojure.jar accounts.clj`
(ns accounts)
(defn account [balance]
(ref {:balance balance}))
(defn deposit [account amount]
{:pre [(pos? amount)]}
(alter account update-in [:balance] + amount))
(defn withdraw [account amount]
{:pre [(pos? amount)]}
(alter account update-in [:balance]
(fn [bal]
(if (> amount bal)
(throw (Exception. "Insufficient funds"))
(- bal amount)))))
(defn balance [account]
(:balance @account))
(defn transfer [from to amount]
(dosync
(withdraw from amount)
(deposit to amount)))
(def transfer-service
(agent nil :error-handler (fn [agnt err]
(println (.getMessage err)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Main script begins here
(def account1 (account 1000))
(def account2 (account 1000))
(println "Account1: " (balance account1))
(println "Account2: " (balance account2))
(send transfer-service
(fn [_] (transfer account1 account2 100)))
(send transfer-service
(fn [_] (transfer account2 account1 200)))
(await transfer-service)
(println "Account1: " (balance account1))
(println "Account2: " (balance account2))
(send transfer-service
(fn [_] (transfer account1 account2 2000)))
(await transfer-service)
(println "Account1: " (balance account1))
(println "Account2: " (balance account2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment