I am trying to send-off
function println
in the transaction.
(ns com.lapots.functional.clojure.transact
(:gen-class))
(defn transfer [from to amount]
(alter
(.balance from) - amount)
(alter
(.balance from) + amount))
(defrecord Account [balance])
(defn -main [& args]
(def account1 (Account. (ref 100)))
(def account2 (Account. (ref 100)))
(def trx-agent (agent 0))
(future
(dosync
(send-off trx-agent println "T2 transfer")
(Thread/sleep 5000)
(transfer account1 account2 10)))
(dosync
(println "T1 transfer")
(transfer account1 account2 10))
(shutdown-agents)
)
If I do like this
(println "T2 transfer")
(Thread/sleep 5000)
it displays message twice as the transaction retries. So I decided to use agents
to make side-effecting operation println
run only once.
But when I do like this
(send-off trx-agent println "T2 transfer")
It does not print T2 transfer
message at all. What is the problem?
You are using shutdown-agents
too soon.
(defn transfer [from to amount]
(println :transfer-enter amount)
(alter
(.balance from) - amount)
(alter
(.balance from) + amount)
(println :transfer-exit amount)
)
(defrecord Account [balance])
(def account1 (Account. (ref 100)))
(def account2 (Account. (ref 100)))
(def trx-agent (agent 0))
(defn -main [& args]
(println :main-enter )
(future
(dosync
(println :t2-enter)
(send-off trx-agent println "agent: T2 transfer")
(Thread/sleep 500)
(transfer account1 account2 20)
(println :t2-exit)
))
(dosync
(println :t1-enter)
(send-off trx-agent println "agent: T1 transfer")
(transfer account1 account2 10)
(println :t1-exit))
(Thread/sleep 2000)
(shutdown-agents)
(println :main-exit )
)
with result:
:main-enter
:t2-enter
:t1-enter
:transfer-enter 10
:transfer-exit 10
:t1-exit
0 agent: T1 transfer
:transfer-enter 20
:t2-enter
:transfer-enter 20
:transfer-exit 20
:t2-exit
nil agent: T2 transfer
:main-exit
So T2 only waits 500 msec now, while T1 runs right away. We wait 2000 msec before calling shutdown-agents
, which will kill all of the agent threads preventing the agent from running.