To facilitate the development of concurrent programs on Multi Core Chips (MCC) and on Shared Memory Systems (SMS) it has been proposed the concept of Transactional Memory, inspired by the concept of Transactions in use with data base systems. The idea is to be able to group a number of read/write memory operations and execute them atomically, either they are successfully carried out even in the presence of concurrent operations, or they fail and are retried. Implementations have been suggested fully in hardware, fully in sofware, and with a mix of hardware and software. We will discuss the software approach. In the following I repeat essentially word per word a presentation made by Simon Peyton Jones of Microsoft. The constructs introduced below are present in STM Haskell: http://haskell.org/ghc which can be downloaded and experimented with.
atomic { .. CODE ...}A possible implementation goes as follows: at the beginning of the atomic code an empty log is created. All write actions of the code are reported in log[name of variable and new value], not done in memory. All read actions actions are first done on the log, and if not there then in memory, in which case the name of the variable and its value are recorded in the log. If the actions aborts, the log is cleared and the action restarted. If the action succeeds then a global lock, or an individual lock on all the variables in the log, linearly ordered, is established. The values of the read variables in the log are compared to their values in memory. If different the action aborts, the log is cleared, and the action restarted. If the same, the action commits, the writes are carried out on memory, the log is deleted, and the locks released.
This construct, in addition to Atomicity, has another important property: Isolation, that is, the intermediate values of the variables appearing in the CODE are not visible to concurrent programs. Viceversa, the CODE does not see changes which may be made to those variables by concurrent programs. This is achieved thanks to the type system of Haskell [mystery] which also prevents the inclusion of operations with side effects such as printing, or activating an effector.
atomic {if n_items== 0 then retry else ...remove from queue... }
atomic {x = queue1.getItem(); queue2.putItem( x ) }
atomic {x = queue1.getItem() ;choose queue2.putItem(x) orElse queue3.putItem(x) }
atomic {x = queue1.getItem() ; choose queue2.putItem(x) orElse queue3.putItem(x) }