About the samples of concurrency problems
The sample of concurrency problems try to implement a simple deposit bank. The customer-visible part of the bank consists of a number of tellers, who have the ability to transfer money from one account to another. In an effort to scale well, the bank is implemented with each teller running in a separate context, which lets all tellers work concurrently. Of course, the simple work of the tellers does not require or even justify this, but the purpose of these samples is to show potential bugs, not to be a practical system. Similarly, no security checks are enforced.
Because data cannot be shared between contexts, the application requires a separate monitor that acts as the bank’s database. The tellers send requests to the bank’s database and receive responses from the database. There is also a simple mechanism to initialize the state of the bank database (SetupAccount event) and for tellers to discover the context in which the database is running. The communication between the bank and the tellers typically needs to get or set an account’s value. The tellers perform the actual arithmetic on a bank account’s value. Each implementation (Race, Deadlock, and Compareswap) differs mainly in the way the tellers and database interact with each other.
Customer interactions with tellers are the same across all implementations. The customer sends a TransferMoney event, specifying which teller to use. It is assumed that customers know the names of tellers, the from and to account, and the amount to transfer. The customer receives a TransferMoneyComplete event when the transfer is complete.
The state of the bank’s accounts can be inspected by sending a SendBalances event to the correlator, which causes the correlator to log and send the balances.
To expose the problems, there are calls to the spinSleep action at key places in the implementations. If the correlator receives an ExposeRaces event, the spinSleep action suspends work by the specified teller for the specified time. This simulates tellers working at different rates, and means that difficult to reproduce conflicts are easier to identify. While this is useful for exposing bugs, it is not suitable for general-purpose sleeps because it consumes CPU time while sleeping and does not let other work in that context get done. This strategy is useful for exposing problems only when you know exactly where to place the sleeps.
Each implementation has its own transfer-sample_name.evt file, which the script sends as each bug is exposed with a different set of input data.