[Haskell-cafe] Stronger STM primitives needed? Or am I just doing
it wrong?
David Roundy
droundy at darcs.net
Wed Apr 23 17:09:36 EDT 2008
On Wed, Apr 23, 2008 at 01:46:53PM -0700, Ryan Ingram wrote:
> On 4/23/08, David Roundy <droundy at darcs.net> wrote:
> > I'm confused as to how your retryUntil gains you anything. If any of the
> > TVars used in the expensive_computation change while waiting for a retry,
> > then the expensive_computation will need to be done again. If none of them
> > change, then we can skip the expensive_computation.
>
> Does the STM runtime do this?
>
> > i.e. how does your broken function using retryUntil differ from the
> > following?
> >
> > broken = atomically $ do
> > v <- expensive_computation :: STM (TVar Int)
> > vv <- readTVar v
> > unless (vv > 50) retry
>
> If the STM runtime does the optimization you suggest, it's not
> different at all.
I doubt it does this, but my point is that you aren't suggesting a new
primitive, you're suggesting an improved runtime. Once you've got your
improved runtime, this optimization is trivial, as far as I can tell. And
without an improved runtime, your function is equivalent to this one.
> But consider this computation:
>
> > -- non-primitive retryUntil:
> > retryUntil v p = do
> > x <- readVar v
> > unless (p x) retry
> >
> > broken2 = atomically $ do
> > (v1, v2) <- expensive_computation :: STM (TVar Int, TVar Int)
> > retryUntil v1 (> 50)
> > x <- expensive_computation2 :: STM Int
> > retryUntil v2 (> x)
>
> If v1 succeeds and v2 fails, then v1 changes to some other value > 50,
> I am sure that the STM runtime as it stands now will re-run
> expensive_computation2.
I suppose it depends on how you rewrite the runtime. Rather than your very
limited retryUntil + caching of results computed in the STM, why not make
this caching explicit, and allow users to write their own more complicated
variants of retryUntil? e.g.
retryUntil2 :: TVar a -> TVar b -> (a -> b -> Bool) -> IO ()
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). Then your
extra-fancy retryUntil could simply be.
retryUntil v p = subatomically $
do x <- readVarRO v
unless (p x) retryRO
The only thing that is special about your retryUntil is that it does not
allow the modification of TVars.
On the other hand, I suspect the whole issue is silly. Is it ever actually
wise to do an expensive calculation in the STM monad? That seems like it's
guaranteed to be a performance nightmare.
--
David Roundy
Department of Physics
Oregon State University
More information about the Haskell-Cafe
mailing list