atomicModifyMutVar2

David Feuer david.feuer at gmail.com
Fri Oct 11 22:59:50 UTC 2019


I don't remember what documentation, if any, it has. You're right that
taking advantage of it is potentially risky. Here's what I think we really
want:

atomicModifyMutVarQ# :: MutVar# s a -> (q -> a) -> (a -> q)  -> State# s ->
(# State# s, a, q #)

where there's a special rule that (q -> a) is "obviously" a selector that
selects a pointer.

On Fri, Oct 11, 2019, 12:56 PM Simon Peyton Jones <simonpj at microsoft.com>
wrote:

> The result doesn't have to be a pair. It can be a tuple of any size at
> all. Indeed, it can even be an arbitrary record type whose first pointer
> field has the appropriate type.
>
>
>
> I think that is 100.0% undocumented, in the code, or in the proposal.  Are
> you sure this is a settled consensus among the interested parties?
>
>
>
> Adopting it would impose new invariants on the representation of values in
> GHC that I am deeply reluctant to impose.  I would much much prefer to
> stick with the pair that is (somewhat) documented.
>
>
>
> About pair vs Unit, yes, I can see (just) your point about why a pair
> might be useful.  Here’s a better example:
>
>
>
> Suppose mv :: MutVar# Int
>
>
>
> atomicModifyMutVar2# mv $ \a ->
>
>   let foo = f a
>
>   in (g foo, foo)
>
>
>
> Now, if f is expensive, *and g is not invertible*, then sharing foo might
> be useful.  It’s hard to think of a credible example, though.  Regardless,
> we should document it.
>
>
>
> Simon
>
>
>
> *From:* David Feuer <david.feuer at gmail.com>
> *Sent:* 11 October 2019 17:03
> *To:* Simon Peyton Jones <simonpj at microsoft.com>
> *Cc:* ghc-devs <ghc-devs at haskell.org>
> *Subject:* Re: atomicModifyMutVar2
>
>
>
> On Fri, Oct 11, 2019, 11:08 AM Simon Peyton Jones <simonpj at microsoft.com>
> wrote:
>
> David
>
> I’m deeply puzzled atomicModifyMutVar2#.  I have read the proposal
> <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fghc-proposals%2Fghc-proposals%2Fblob%2Fmaster%2Fproposals%2F0149-atomicModifyMutVar.rst&data=02%7C01%7Csimonpj%40microsoft.com%7C10950014fe9d46a6682508d74e649537%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637064066214164213&sdata=2phccb9r%2Fcg4xs7beKByn%2F1Ivxz7kvN5xkejhOpDfg8%3D&reserved=0>,
> and the comments in primops.txt.pp (reproduced below).
> Question 1
>
> I think the “real” type of atomicModifyMutVar2 is
>
> atomicModifyMutVar2# :: MutVar# s a
>
>                      -> (a -> (a,b))
>
>                      -> State# s
>
>                      -> (# State# s, a, (a, b) #)
>
>
>
> Close, but not quite. The result doesn't have to be a pair. It can be a
> tuple of any size at all. Indeed, it can even be an arbitrary record type
> whose first pointer field has the appropriate type.
>
>
>
> Nowhere is this explicitly stated, but I believe that the intended
> semantics of a call
>
> case (atomicModifyMutVar2# mv f s) of (# s’, x, r #) -> blah
>
> Then, suppose the old value of the MutVar was ‘*old’*
>
>    - The primop builds a thunk  *t *= *f old*
>    - The new value of the mutable variable is *(fst t)*
>    - The result *r* is t
>    - The result *x* is *old*
>
> Question: is that correct?   We should state it explicitly.
>
> Yes, that sounds right.
>
> Question 2
>
> Next question: Why does f have to return a pair?  So far as I can tell,
> it’s only so that a client can force it.   The ‘b’ part never seems to play
> a useful role.   So we could equally well have had
>
> atomicModifyMutVar2# :: MutVar# s a
>
>                      -> (a -> Box a)
>
>                      -> State# s
>
>                      -> (# State# s, a, Unit a #)
>
> where Unit is defined in Data.Tuple
>
>     data Unit a = Unit a
>
> Now you can force the result of (f old), just as with a pair.  But the ‘b’
> would no longer complicate matters.
>
> Question: is the ‘b’ in the pair significant?   Or could we use Unit?
>
> Yes, it's somewhat significant. You actually can use Unit with the new
> primop (it's a tuple of arity 1), so that option is free. But using a pair
> gets you a bit more: you can build a thunk that's *shared* between the
> value installed in the MutVar and the one returned to the outside. Consider
>
>
>
> atomicModifyMutVar2# mv $ \a ->
>
>   let foo = expensive_computation a
>
>   in ([3,foo], foo)
>
> Question 3
>
> In the comments below you say "but we don't know about pairs here”.   Are
> you sure?  What stops you importing Data.Tuple into GHC.Prim?   This fancy
> footwork is one more complication, if it could be avoided.
>
> That whole regime came before my time, but since we win a bit by *not*
> fixing it, o wouldn't jump on it too quick.
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-devs/attachments/20191011/298a606a/attachment.html>


More information about the ghc-devs mailing list