Skip to content

Instantly share code, notes, and snippets.

@ELLIOTTCABLE
Created May 30, 2010 03:03
Show Gist options
  • Save ELLIOTTCABLE/418738 to your computer and use it in GitHub Desktop.
Save ELLIOTTCABLE/418738 to your computer and use it in GitHub Desktop.
Solving the classic banking concurrency problem with Paws
bank.client ← list clone
heir.cache ← list clone
definition(‘heir.cache’) depth ← 0 ; “Heirs’ lookups will ‘overlook’ this `heir.cache` definition.”
“This will either retrieve the existing client object from the cache, or create a new one with its `id` set.”
clone ← routine {
result(heir.cache[argument] ⇤ up
id ← argument
client ← HTTP client clone
host ← ‘api.awesome-bank.co.uk’
port ← 8088
)
}
“Since this routine is declared as ‘atomic,’ it will never be scheduled for execution in parallel with any
other routines that conflict with its ownership at runtime.”
transfer ← routine {
available.from ← `from client get(‘/funds_available’, params: (account: `from id))
if (available.from ≥ argument)
from ← `from client get(‘/funds’, params: (account: `from id))
to ← `to client get(‘/funds’, params: (account: `to id))
`from client post(‘/funds’, params: (account: `from id, funds: from − argument))
`to client post(‘/funds’, params: (account: `to id, funds: to + argument))
}
transfer atomic!
open.account ← routine {
id ← `client post(‘/open’, params: (account: `id))
result(mint ← `clone(id))
(from: this, to: mint)transfer(argument)
}
“This is a basic example of how Paws makes concurrent applications easy to write. In this example, we have
shared resources (bank accounts) for which the order-of-access is critical.
In this example, if the HTTP requests were to happen out-of-order, then somebody would end up with more or less
money than they should have, which is a critical failure of the program. Paws prevents that.”
“To clarify what is going on, we’re going to have a little story problem (OMG YAY!) Specifically, we have five
people: Paul and Peter, Jasmine, and then Mark and Mindy. Paul and Peter will transfer money between one
another, and Jasmine will also transfer some money with Peter. Mark and Mindy, meanwhile, will transfer money
amongst eachother, without any relation or interaction with the other three.
In a non-concurrent system, this would be a series of safe operations; however, it would be slow. In an
improperly designed concurrent system, the reads and writes to the shared resources might become interleaved,
causing the critical failure described above. In a properly designed concurrent system, unrelated accesses will
have the opportunity to proceed concurrently, saving processing time, while still preventing dangerous forms of
simultaneous access to shared resources.”
“There are going to be three different real-world transactions going on here; we’re going to simulate this with
three separate routines (the `do` routine itself simply takes a block, and executes it—nothing special.) By
default, in Paws, these will all three run concurrently.”
“First, Paul is going to give Peter a small amount of money, and then realize he didn’t need quite that much.”
do {
“The `bank.client` is a fictional library, that provides a Paws interface to a bank’s HTTP database. It does
nothing magical, concurrency-wise; in this example, it simply sets up an object for us that has an account
number, and some methods to make authenticated HTTP requests to the bank’s HTTP API.”
Peter ← bank.client clone(800,223)
Paul ← bank.client clone(800,490)
“Now that we have handles for those accounts, we’re going to transfer some money.”
(from: Peter, to: Paul)transfer(100$)
“Since that was a bit too much, Paul is going to transfer a little back.”
(from: Paul, to: Peter)transfer(20$)
}
“Now, a related but separate operation: Peter is going to open an account for Jasmine, which involves depositing
a little of his money to get her started.”
do {
Peter ← bank.client clone(800,223)
Jasmine ← Peter open.account(with: 25$)
}
“Finally: In a completely unrelated operation, Mark and Mindy transfer some money.”
do {
Mark ← bank.client clone(796,724)
Mindy ← bank.client clone(424,634)
(from: Mark, to: Mindy)transfer(1,500$)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment