Ryan Ingram said: > So, if have a transaction T that is waiting inside "retry" for a > variable that it read to change, and a variable that is only accessed > in a "subatomic" part of T is changed, we can try running the > subatomic computation first. Here are the four cases: > > 1) The subatomic computation succeeded before and still succeeded. > Then we know the end result of the computation is unaffected, and will > still retry. No need to do anything. > 2) The subatomic computation succeeded before and now fails (calls > 'retry' or retryRO'). Then we know that the computation will now fail > at this earlier point. Mark the change to "fail" in the transaction > log and leave the computation in the "waiting for retry" state. > 3) The subatomic computation failed before and still fails. See (1) > 4) The subatomic computation failed before and now succeeds. The > result of the entire computation can change, we should now re-run the > entire computation.
I'm trying to figure out whether subatomic could be weakened to allow writes as well as reads. I don't think this change would affect cases 2 to 4 above. But in case 1, the subatomic computation might perform a different set of writes, which might affect the outcome of the outer computation, so it is not safe to continue blocking. It's case 1 which makes retryUntil (and subatomic) stronger than readTVarWhen. If it's not possible to weaken subatomic to allow writes, without affecting case 1, then I think this also means that subatomic/retryUntil is stronger than the hypothetical "continuation-logging" implementation previously hinted at by David, apfelmus and myself (that is, one which treats each individual read as a kind of checkpoint, by recording the read's continuation in the transaction log, and using that continuation to restart the blocked transaction). 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. It could have a simpler type, and the semantics of "id": subatomic :: STM a -> STM a If the subatomic transaction turns out to be read-only, then we get the benefit of all four cases Ryan describes above. If it turns out to be read-write, we only get the benefit of cases 2 to 4, while case 1 must restart. It doesn't matter if the subatomic transaction captures variables which depend on previous reads, since changes to those reads would cause a restart regardless of the outcome of the subatomic transaction. Moreover, note that the hypothetical "continuation-logging" implementation could implement (m >>= k) by implicitly wrapping every m in a call to subatomic. Of course, that would require a lot of speculative book-keeping. I think this means that subatomic is not a fundamental abstraction, but could be a useful pragmatic optimisation. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe