-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathbank-account.stmx.lisp
85 lines (60 loc) · 2.57 KB
/
bank-account.stmx.lisp
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
;; -*- lisp -*-
;; This file is part of STMX.
;; Copyright (c) 2013-2016 Massimiliano Ghilardi
;;
;; This library is free software: you can redistribute it and/or
;; modify it under the terms of the Lisp Lesser General Public License
;; (http://opensource.franz.com/preamble.html), known as the LLGPL.
;;
;; This library is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty
;; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
;; See the Lisp Lesser General Public License for more details.
(in-package :cl-user)
(defpackage #:stmx.example.bank-account.stmx
(:use #:cl #:stmx)
(:import-from #:stmx.lang
#:new #:defprint-object))
(in-package :stmx.example.bank-account.stmx)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(deftype unsigned-fixnum () '(integer 0 #.most-positive-fixnum))
(transactional
(defclass account ()
((balance :initform 0 :initarg :balance :type unsigned-fixnum :accessor account-balance)
(name :initform "" :initarg :name :type string :reader account-name
:transactional nil))))
(defprint-object (obj account :identity nil)
(format t "~S ~S" (account-name obj) (account-balance obj)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun withdraw (delta account)
"decrease ACCOUNT balance by DELTA. return T if successful"
(declare (type unsigned-fixnum delta)
(type account account))
(atomic
(when (>= (account-balance account) delta)
(decf (account-balance account) delta)
t)))
(defun deposit (delta account)
"increase ACCOUNT balance by DELTA. return T if successful"
(declare (type unsigned-fixnum delta)
(type account account))
(atomic
(when (<= (account-balance account) (- most-positive-fixnum delta))
(incf (account-balance account) delta)
t)))
(defun transfer (delta account1 account2)
"transfer DELTA from ACCOUNT1 to ACCOUNT2. return t if successful."
(declare (type unsigned-fixnum delta)
(type account account1 account2))
(atomic
(when (withdraw delta account1)
(if (deposit delta account2)
t
(if (deposit delta account1)
t
(error "cannot happen! cannot deposit ~S back into ~S!" delta account1))))))
(defparameter *account1* (new 'account :name "Mario rossi" :balance 1000))
(defparameter *account2* (new 'account :name "Giuseppe Verdi"))
(defun test-bank-accounts (&optional (account1 *account1*) (account2 *account2*))
(log:info (transfer 700 account1 account2))
(log:info (transfer 500 account2 account1)))