source: CIVL/examples/concurrency/bank.cvl@ b968f34

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since b968f34 was 9fb69d3, checked in by Manchun Zheng <zmanchun@…>, 13 years ago

cleaned up examples/tests in concurrency folder.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@421 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/* simple exercise in multitasking verification using CIVL.
2 * Commandline execution:
3 * civl verify -inputNUM_ACCOUNTS=5 bank.cvl
4 * */
5#include<civlc.h>
6
7$input int NUM_ACCOUNTS;
8
9/* ========================================================================
10 constants
11 */
12#define true 1
13#define false 0
14
15/* ========================================================================
16 prototypes
17 */
18
19void init();
20int withdraw( int account_num, int amount );
21int deposit( int account_num, int amount );
22int balance( int account_num );
23int transfer( int to_account_num, int from_account_num, int amount );
24void lock_account( int account_num );
25void unlock_account( int account_num );
26
27/* ========================================================================
28 global variables
29 */
30int account_balance[ NUM_ACCOUNTS ];
31int account_locked[ NUM_ACCOUNTS ];
32
33/* ======================================================================== */
34void init ()
35{
36 int acct_num;
37
38 for ( acct_num= 0; acct_num < NUM_ACCOUNTS; acct_num++ ) {
39 account_balance[acct_num]= 0;
40 account_locked[acct_num]= false;
41 }
42}
43
44/* ======================================================================== */
45int withdraw( int account_num, int amount )
46/* Return value: false if success, true if an error occurred
47 */
48{
49 int result;
50
51 $assume 0 <= account_num;
52 $assume account_num <= NUM_ACCOUNTS;
53 $assume amount >= 0;
54 // begin transaction
55 lock_account( account_num );
56 if ( account_balance[account_num] >= amount ) {
57 account_balance[account_num]= account_balance[account_num]- amount;
58 result= false;
59 } else {
60 result= true;
61 }
62 // end transaction
63 unlock_account( account_num );
64 return result;
65}
66
67/* ======================================================================== */
68int deposit( int account_num, int amount )
69/* Return value: false if success, true if an error occurred
70 */
71{
72 $assume 0 <= account_num;
73 $assume account_num <= NUM_ACCOUNTS;
74 $assume amount >= 0;
75 // begin transaction
76 lock_account( account_num );
77 account_balance[account_num]= account_balance[account_num]+ amount;
78 // end transaction
79 unlock_account( account_num );
80 return false;
81}
82
83/* ======================================================================== */
84int balance( int account_num )
85/* Return value: the balance of the indicated account
86 */
87{
88 int balance= 0;
89
90 $assume 0 <= account_num;
91 $assume account_num <= NUM_ACCOUNTS;
92 // begin transaction
93 lock_account( account_num );
94 balance= account_balance[account_num];
95 // end transaction
96 unlock_account( account_num );
97 return account_balance[account_num];
98}
99
100/* ======================================================================== */
101int transfer( int to_account_num, int from_account_num, int amount )
102/* Return value: false if success, true if an error occurred
103 */
104{
105 int result= false;
106
107 $assume 0 <= to_account_num;
108 $assume to_account_num <= NUM_ACCOUNTS;
109 $assume 0 <= from_account_num;
110 $assume from_account_num <= NUM_ACCOUNTS;
111 $assume from_account_num != to_account_num;
112 $assume amount >= 0;
113 // begin transaction
114 if ( from_account_num < to_account_num ) {
115 lock_account( from_account_num );
116 lock_account( to_account_num );
117 } else {
118 lock_account( to_account_num );
119 lock_account( from_account_num );
120 }
121 if ( account_balance[from_account_num] >= amount ) {
122 account_balance[from_account_num]-= amount;
123 account_balance[to_account_num]+= amount;
124 result= false;
125 } else {
126 result= true;
127 }
128 // end transaction
129 if ( from_account_num < to_account_num ) {
130 unlock_account( to_account_num );
131 unlock_account( from_account_num );
132 } else {
133 unlock_account( from_account_num );
134 unlock_account( to_account_num );
135 }
136 return result;
137}
138
139/* ======================================================================== */
140/* main() and its helper ftns
141 */
142void main_a()
143{
144 $atomic {
145 withdraw( 0, 50 );
146 transfer( 0, 1, 50 );
147 deposit( 2, 100 );
148 }
149}
150
151void main_b()
152{
153 $atomic {
154 deposit( 1, 10 );
155 withdraw( 2, 50 );
156 transfer( 2, 0, 20 );
157 }
158}
159
160void main()
161{
162 int acct_num = 0;
163 $proc proc_a;
164 $proc proc_b;
165
166 $atomic {
167 init();
168 /* give all accounts some money */
169 for ( acct_num= 0; acct_num < NUM_ACCOUNTS; acct_num++ ) {
170 deposit( acct_num, 100 );
171 }
172 }
173 $atomic{
174 proc_a= $spawn main_a();
175 proc_b= $spawn main_b();
176 $wait proc_a;
177 $wait proc_b;
178 }
179}
180
181/* ======================================================================== */
182void lock_account( int account_num )
183{
184 $assume 0 <= account_num;
185 $assume account_num <= NUM_ACCOUNTS;
186 // this needs to happen atomically -- does it?
187 $when (account_locked[account_num] == false) account_locked[account_num]= true;
188}
189
190/* ======================================================================== */
191void unlock_account( int account_num )
192{
193 $assume 0 <= account_num;
194 $assume account_num <= NUM_ACCOUNTS;
195
196 account_locked[ account_num ]= false;
197}
198/* ======================================================================== */
199/* end of file */
Note: See TracBrowser for help on using the repository browser.