
David Roundy wrote:
A simple primitive to do this (in combination with a totally rewritten STM runtime) would be
subatomically :: ReadOnlySTM a -> STM ()
which would run a STM computation that is guaranteed to have no side-effects (i.e. can't write to TVars) and ignore its results (and let the runtime know that the results have been ignored).
Matthew Brecknell wrote:
Nevertheless, the distinction between read-only and read-write transactions does not necessarily have to occur at the level of types. STM is fundamentally a dynamic approach to concurrency control, so I think it would make sense for transactions to *dynamically* determine whether they are read-only or read-write, as they compose with each other.
In that case, we can treat subatomic as a "hint" to the STM runtime.
subatomic :: STM a -> STM ()
Concerning this question of whether the argument to subatomic should statically or dynamically be known to be read-only, there is also the option of collapsing ReadOnlySTM a and STM a by changing the semantics of writeTVar . I mean, writeTVar can be used for two different things: 1) communicate with other threads, i.e. crossing atomically boundaries 2) communicating inside a single thread/STM action à la mutable state (IORef). We only want 1), but 2) is expendable, we can always use parameters to pass state around or wrap the whole thing into a state monad. For 1), it's enough to have a primitive scheduleWriteTVar :: TVar a -> a -> STM () that ensures to write the TVar at the very end of the atomically block. (This is similar to scheduleIO :: IO a -> STM ()). In other words, the current STM semantics can be implemented in terms of ReadOnlySTM assuming that the latter has such a primitive for scheduling. type ReadOnlySTM a = StateT TVarEnvironment STM a Regards, apfelmus