[rucksack-devel] WITH-TRANSACTION
Nikodemus Siivola
nikodemus at random-state.net
Sat May 20 10:13:58 UTC 2006
The current WITH-TRANSACTION looks wrong to me: non-local exists leave the
transaction hanging. Below is a sketch for a more robust one, that also
as a convenience returns the primary value of the BODY as its second value.
(defmacro with-transaction ((&rest args
&key (rucksack '(current-rucksack))
&allow-other-keys)
&body body)
(let ((committed (gensym "COMMITTED"))
(transaction (gensym "TRANSACTION"))
(result (gensym "RESULT")))
`(let ((,transaction nil))
(loop named ,transaction
(with-simple-restart (retry "Retry ~S" ,transaction)
(let ((,committed nil)
(,result nil))
(unwind-protect
(progn
;; Use a local variable for the transaction so that nothing
;; can replace it from underneath us, and only then bind
;; it to *TRANSACTION*.
(setf ,transaction (transaction-start :rucksack ,rucksack , at args))
(let ((*transaction* ,transaction))
(with-simple-restart (abort "Abort ~S" ,transaction)
(setf ,result , at body)
(transaction-commit ,transaction)
(setf ,committed t)))
;; Normal exit from the WITH-SIMPLE-RESTART above -- either
;; everything went well or we aborted -- the ,COMMITTED will tell
;; us. In either case we jump out of the RETRY loop.
(return-from ,transaction (values ,committed ,result)))
(unless ,committed
(transaction-rollback ,transaction)))))
;; Normal exit from the above block -- we selected the RETRY restart.
))))
Cheers,
-- Nikodemus Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs."
More information about the rucksack-devel
mailing list