Hash :
5f5fc369
Author :
Thomas de Grivel
Date :
2022-11-18T19:46:56
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
;; rollback - rollback functions
;; Copyright 2012-2022 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
;; are included in all copies and substantial portions of this
;; software.
;;
;; THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
;; PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
;; AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
;; THIS SOFTWARE.
(defpackage :rollback
(:use :cl)
(:export #:rollback-function
#:rollback
#:with-rollback
#:with-rollback*))
(in-package :rollback)
(defun rollback-function (op)
(get op 'rollback-function))
(defun set-rollback-function (op rollback-fn)
(setf (get op 'rollback-function) rollback-fn))
(defsetf rollback-function set-rollback-function)
(defun rollback (op &rest args)
(let ((rollback-fn (rollback-function op)))
(unless rollback-fn
(error "Undefined rollback function for ~S" op))
(apply rollback-fn args)))
(defmacro with-rollback ((fun &rest args) &body body)
(let ((rollback (gensym "ROLLBACK-"))
(g!args (mapcar (lambda (x)
(declare (ignore x))
(gensym "ARG-"))
args)))
`(let ((,rollback t)
,@(loop
for var in g!args
for value in args
collect `(,var ,value)))
(,fun ,@g!args)
(unwind-protect (prog1 ,(if (= 1 (length body))
(car body)
`(progn ,@body))
(setf ,rollback nil))
(when ,rollback
(rollback ',fun ,@g!args))))))
(defmacro with-rollback* (&body forms)
(reduce (lambda (body form)
(if body
`(with-rollback ,form
,body)
form))
(reverse forms)))