Proposal: Add atomic IORef operations to Data.IORef

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Proposal: Add atomic IORef operations to Data.IORef

David Feuer
GHC.IORef currently exports

atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
atomicSwapIORef :: IORef a -> a -> IO a

atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
both the old value in the IORef and the full result of applying the
user-supplied function to that. This is a pretty thin wrapper around
the newish atomicModifyMutVar2# primop, which has replaced the less
powerful atomicModifyMutVar#.

atomicSwapIORef atomically installs a user-supplied value in an IORef
and returns the old value. It is currently implemented using
atomicModifyIORef2, but it can and should be reimplemented using its
own, more efficient primop.

I propose to add both of these functions to Data.IORef.

David
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

chessai .
+1 with sufficient documentation

On Fri, Jan 15, 2021, 14:06 David Feuer <[hidden email]> wrote:
GHC.IORef currently exports

atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
atomicSwapIORef :: IORef a -> a -> IO a

atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
both the old value in the IORef and the full result of applying the
user-supplied function to that. This is a pretty thin wrapper around
the newish atomicModifyMutVar2# primop, which has replaced the less
powerful atomicModifyMutVar#.

atomicSwapIORef atomically installs a user-supplied value in an IORef
and returns the old value. It is currently implemented using
atomicModifyIORef2, but it can and should be reimplemented using its
own, more efficient primop.

I propose to add both of these functions to Data.IORef.

David
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

Alexey Kuleshevich
In reply to this post by David Feuer
Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.

So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef


Alexey.


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, January 15, 2021 11:05 PM, David Feuer <[hidden email]> wrote:

> GHC.IORef currently exports
>
> atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
> atomicSwapIORef :: IORef a -> a -> IO a
>
> atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
> both the old value in the IORef and the full result of applying the
> user-supplied function to that. This is a pretty thin wrapper around
> the newish atomicModifyMutVar2# primop, which has replaced the less
> powerful atomicModifyMutVar#.
>
> atomicSwapIORef atomically installs a user-supplied value in an IORef
> and returns the old value. It is currently implemented using
> atomicModifyIORef2, but it can and should be reimplemented using its
> own, more efficient primop.
>
> I propose to add both of these functions to Data.IORef.
>
> David
>
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

David Feuer
I disagree. I believe we should offer both atomicModifyIORef2 and an
atomicModifyIORef2'. The latter should force the new value in the
IORef but, unlike atomicModifyIORef', should not force the returned
value. Or if you and others prefer, we could offer a strict
atomicModifyIORef and a lazy atomicModifyIORef2Lazy. As a Haskell
programmer, I really don't want totally polymorphic values getting
forced behind my back. It's actually possible to write an even lazier
version that doesn't even force the function result pair, but I don't
think that's a very useful idea.

One other thing: the natural approach to atomicModifyIORef2' uses a
"half-strict pair" type

    data HSPair a b = HSPair !a b
    atomicModifyIORef2' :: IORef a -> (a -> HSPair a b) -> IO (a, HSPair a b)

I don't know to what extent users are willing to tolerate such an
extra datatype.

Side note: the peculiarly strict behavior of atomicModifyIORef' is a
result of the poor design of the old atomicModifyMutVar# primop.

On Fri, Jan 15, 2021 at 3:19 PM Alexey Kuleshevich <[hidden email]> wrote:

>
> Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.
>
> So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef
>
>
> Alexey.
>
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Friday, January 15, 2021 11:05 PM, David Feuer <[hidden email]> wrote:
>
> > GHC.IORef currently exports
> >
> > atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
> > atomicSwapIORef :: IORef a -> a -> IO a
> >
> > atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
> > both the old value in the IORef and the full result of applying the
> > user-supplied function to that. This is a pretty thin wrapper around
> > the newish atomicModifyMutVar2# primop, which has replaced the less
> > powerful atomicModifyMutVar#.
> >
> > atomicSwapIORef atomically installs a user-supplied value in an IORef
> > and returns the old value. It is currently implemented using
> > atomicModifyIORef2, but it can and should be reimplemented using its
> > own, more efficient primop.
> >
> > I propose to add both of these functions to Data.IORef.
> >
> > David
> >
> > Libraries mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
>
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

David Feuer
In reply to this post by David Feuer
Please do feel free to suggest a better name. I would certainly have
named it better had I been able to think of one.

On Fri, Jan 15, 2021 at 3:33 PM <[hidden email]> wrote:

>
> I would suggest better naming that suffixing with '2', if the suggestion was to add them with the same names as GHC.IORef
> On 15 Jan 2021, 20:05 +0000, David Feuer <[hidden email]>, wrote:
>
> GHC.IORef currently exports
>
>
> atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
>
> atomicSwapIORef :: IORef a -> a -> IO a
>
>
> atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
>
> both the old value in the IORef and the full result of applying the
>
> user-supplied function to that. This is a pretty thin wrapper around
>
> the newish atomicModifyMutVar2# primop, which has replaced the less
>
> powerful atomicModifyMutVar#.
>
>
> atomicSwapIORef atomically installs a user-supplied value in an IORef
>
> and returns the old value. It is currently implemented using
>
> atomicModifyIORef2, but it can and should be reimplemented using its
>
> own, more efficient primop.
>
>
> I propose to add both of these functions to Data.IORef.
>
>
> David
>
> _______________________________________________
>
> Libraries mailing list
>
> [hidden email]
>
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

Alexey Kuleshevich
In reply to this post by David Feuer
I totally agree with everything that you just said. Sorry, I should have said originally "-1 for adding JUST these lazy versions". As long as there are strict versions (whatever the names they might get, IMHO Lazy suffix is nice) and a warning on lazy versions about leaking memory, then I am 100% on board as well. Also +1 on not forcing the result.

Alexey.

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, January 15, 2021 11:29 PM, David Feuer <[hidden email]> wrote:

> I disagree. I believe we should offer both atomicModifyIORef2 and an
> atomicModifyIORef2'. The latter should force the new value in the
> IORef but, unlike atomicModifyIORef', should not force the returned
> value. Or if you and others prefer, we could offer a strict
> atomicModifyIORef and a lazy atomicModifyIORef2Lazy. As a Haskell
> programmer, I really don't want totally polymorphic values getting
> forced behind my back. It's actually possible to write an even lazier
> version that doesn't even force the function result pair, but I don't
> think that's a very useful idea.
>
> One other thing: the natural approach to atomicModifyIORef2' uses a
> "half-strict pair" type
>
> data HSPair a b = HSPair !a b
> atomicModifyIORef2' :: IORef a -> (a -> HSPair a b) -> IO (a, HSPair a b)
>
> I don't know to what extent users are willing to tolerate such an
> extra datatype.
>
> Side note: the peculiarly strict behavior of atomicModifyIORef' is a
> result of the poor design of the old atomicModifyMutVar# primop.
>
> On Fri, Jan 15, 2021 at 3:19 PM Alexey Kuleshevich [hidden email] wrote:
>
> > Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.
> > So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef
> > Alexey.
> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > On Friday, January 15, 2021 11:05 PM, David Feuer [hidden email] wrote:
> >
> > > GHC.IORef currently exports
> > > atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
> > > atomicSwapIORef :: IORef a -> a -> IO a
> > > atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
> > > both the old value in the IORef and the full result of applying the
> > > user-supplied function to that. This is a pretty thin wrapper around
> > > the newish atomicModifyMutVar2# primop, which has replaced the less
> > > powerful atomicModifyMutVar#.
> > > atomicSwapIORef atomically installs a user-supplied value in an IORef
> > > and returns the old value. It is currently implemented using
> > > atomicModifyIORef2, but it can and should be reimplemented using its
> > > own, more efficient primop.
> > > I propose to add both of these functions to Data.IORef.
> > > David
> > > Libraries mailing list
> > > [hidden email]
> > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

David Feuer
Cool. Do you also want a strict atomicSwapIORef'?

On Fri, Jan 15, 2021 at 3:38 PM Alexey Kuleshevich <[hidden email]> wrote:

>
> I totally agree with everything that you just said. Sorry, I should have said originally "-1 for adding JUST these lazy versions". As long as there are strict versions (whatever the names they might get, IMHO Lazy suffix is nice) and a warning on lazy versions about leaking memory, then I am 100% on board as well. Also +1 on not forcing the result.
>
> Alexey.
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Friday, January 15, 2021 11:29 PM, David Feuer <[hidden email]> wrote:
>
> > I disagree. I believe we should offer both atomicModifyIORef2 and an
> > atomicModifyIORef2'. The latter should force the new value in the
> > IORef but, unlike atomicModifyIORef', should not force the returned
> > value. Or if you and others prefer, we could offer a strict
> > atomicModifyIORef and a lazy atomicModifyIORef2Lazy. As a Haskell
> > programmer, I really don't want totally polymorphic values getting
> > forced behind my back. It's actually possible to write an even lazier
> > version that doesn't even force the function result pair, but I don't
> > think that's a very useful idea.
> >
> > One other thing: the natural approach to atomicModifyIORef2' uses a
> > "half-strict pair" type
> >
> > data HSPair a b = HSPair !a b
> > atomicModifyIORef2' :: IORef a -> (a -> HSPair a b) -> IO (a, HSPair a b)
> >
> > I don't know to what extent users are willing to tolerate such an
> > extra datatype.
> >
> > Side note: the peculiarly strict behavior of atomicModifyIORef' is a
> > result of the poor design of the old atomicModifyMutVar# primop.
> >
> > On Fri, Jan 15, 2021 at 3:19 PM Alexey Kuleshevich [hidden email] wrote:
> >
> > > Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.
> > > So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef
> > > Alexey.
> > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > > On Friday, January 15, 2021 11:05 PM, David Feuer [hidden email] wrote:
> > >
> > > > GHC.IORef currently exports
> > > > atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
> > > > atomicSwapIORef :: IORef a -> a -> IO a
> > > > atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
> > > > both the old value in the IORef and the full result of applying the
> > > > user-supplied function to that. This is a pretty thin wrapper around
> > > > the newish atomicModifyMutVar2# primop, which has replaced the less
> > > > powerful atomicModifyMutVar#.
> > > > atomicSwapIORef atomically installs a user-supplied value in an IORef
> > > > and returns the old value. It is currently implemented using
> > > > atomicModifyIORef2, but it can and should be reimplemented using its
> > > > own, more efficient primop.
> > > > I propose to add both of these functions to Data.IORef.
> > > > David
> > > > Libraries mailing list
> > > > [hidden email]
> > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
>
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

Alexey Kuleshevich
Despite that this one is easy `atomicSwapIORef' ref !a = atomicSwapIORef ref a` I think it is important to include it. I also think `atomicWriteIORef'` should be added as well. Point is that most of the time in a concurrent setup it is the thread that does the IORef modification should be responsible for computing the value that is being written. This is important not only for performance but also for error handling.

Alexey.


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Saturday, January 16, 2021 12:01 AM, David Feuer <[hidden email]> wrote:

> Cool. Do you also want a strict atomicSwapIORef'?
>
> On Fri, Jan 15, 2021 at 3:38 PM Alexey Kuleshevich [hidden email] wrote:
>
> > I totally agree with everything that you just said. Sorry, I should have said originally "-1 for adding JUST these lazy versions". As long as there are strict versions (whatever the names they might get, IMHO Lazy suffix is nice) and a warning on lazy versions about leaking memory, then I am 100% on board as well. Also +1 on not forcing the result.
> > Alexey.
> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > On Friday, January 15, 2021 11:29 PM, David Feuer [hidden email] wrote:
> >
> > > I disagree. I believe we should offer both atomicModifyIORef2 and an
> > > atomicModifyIORef2'. The latter should force the new value in the
> > > IORef but, unlike atomicModifyIORef', should not force the returned
> > > value. Or if you and others prefer, we could offer a strict
> > > atomicModifyIORef and a lazy atomicModifyIORef2Lazy. As a Haskell
> > > programmer, I really don't want totally polymorphic values getting
> > > forced behind my back. It's actually possible to write an even lazier
> > > version that doesn't even force the function result pair, but I don't
> > > think that's a very useful idea.
> > > One other thing: the natural approach to atomicModifyIORef2' uses a
> > > "half-strict pair" type
> > > data HSPair a b = HSPair !a b
> > > atomicModifyIORef2' :: IORef a -> (a -> HSPair a b) -> IO (a, HSPair a b)
> > > I don't know to what extent users are willing to tolerate such an
> > > extra datatype.
> > > Side note: the peculiarly strict behavior of atomicModifyIORef' is a
> > > result of the poor design of the old atomicModifyMutVar# primop.
> > > On Fri, Jan 15, 2021 at 3:19 PM Alexey Kuleshevich [hidden email] wrote:
> > >
> > > > Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.
> > > > So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef
> > > > Alexey.
> > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > > > On Friday, January 15, 2021 11:05 PM, David Feuer [hidden email] wrote:
> > > >
> > > > > GHC.IORef currently exports
> > > > > atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
> > > > > atomicSwapIORef :: IORef a -> a -> IO a
> > > > > atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
> > > > > both the old value in the IORef and the full result of applying the
> > > > > user-supplied function to that. This is a pretty thin wrapper around
> > > > > the newish atomicModifyMutVar2# primop, which has replaced the less
> > > > > powerful atomicModifyMutVar#.
> > > > > atomicSwapIORef atomically installs a user-supplied value in an IORef
> > > > > and returns the old value. It is currently implemented using
> > > > > atomicModifyIORef2, but it can and should be reimplemented using its
> > > > > own, more efficient primop.
> > > > > I propose to add both of these functions to Data.IORef.
> > > > > David
> > > > > Libraries mailing list
> > > > > [hidden email]
> > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

David Feuer
The error handling situation for modification operations is somewhat deceptive. Unlike MVar operations, where the modifying thread can be fully responsible for exceptions, a thread can *try* to force the modified IORef value, but it may *actually* be forced by another thread if that thread gets there first. Someone using atomicModifyIORef2' should be very careful not to produce bottom as the new IORef value. Similarly, they must not use unsafePerformIO to produce the result if the IO in question must be performed in a particular thread.

On Fri, Jan 15, 2021, 4:13 PM Alexey Kuleshevich <[hidden email]> wrote:
Despite that this one is easy `atomicSwapIORef' ref !a = atomicSwapIORef ref a` I think it is important to include it. I also think `atomicWriteIORef'` should be added as well. Point is that most of the time in a concurrent setup it is the thread that does the IORef modification should be responsible for computing the value that is being written. This is important not only for performance but also for error handling.

Alexey.


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Saturday, January 16, 2021 12:01 AM, David Feuer <[hidden email]> wrote:

> Cool. Do you also want a strict atomicSwapIORef'?
>
> On Fri, Jan 15, 2021 at 3:38 PM Alexey Kuleshevich [hidden email] wrote:
>
> > I totally agree with everything that you just said. Sorry, I should have said originally "-1 for adding JUST these lazy versions". As long as there are strict versions (whatever the names they might get, IMHO Lazy suffix is nice) and a warning on lazy versions about leaking memory, then I am 100% on board as well. Also +1 on not forcing the result.
> > Alexey.
> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > On Friday, January 15, 2021 11:29 PM, David Feuer [hidden email] wrote:
> >
> > > I disagree. I believe we should offer both atomicModifyIORef2 and an
> > > atomicModifyIORef2'. The latter should force the new value in the
> > > IORef but, unlike atomicModifyIORef', should not force the returned
> > > value. Or if you and others prefer, we could offer a strict
> > > atomicModifyIORef and a lazy atomicModifyIORef2Lazy. As a Haskell
> > > programmer, I really don't want totally polymorphic values getting
> > > forced behind my back. It's actually possible to write an even lazier
> > > version that doesn't even force the function result pair, but I don't
> > > think that's a very useful idea.
> > > One other thing: the natural approach to atomicModifyIORef2' uses a
> > > "half-strict pair" type
> > > data HSPair a b = HSPair !a b
> > > atomicModifyIORef2' :: IORef a -> (a -> HSPair a b) -> IO (a, HSPair a b)
> > > I don't know to what extent users are willing to tolerate such an
> > > extra datatype.
> > > Side note: the peculiarly strict behavior of atomicModifyIORef' is a
> > > result of the poor design of the old atomicModifyMutVar# primop.
> > > On Fri, Jan 15, 2021 at 3:19 PM Alexey Kuleshevich [hidden email] wrote:
> > >
> > > > Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.
> > > > So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef
> > > > Alexey.
> > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > > > On Friday, January 15, 2021 11:05 PM, David Feuer [hidden email] wrote:
> > > >
> > > > > GHC.IORef currently exports
> > > > > atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
> > > > > atomicSwapIORef :: IORef a -> a -> IO a
> > > > > atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
> > > > > both the old value in the IORef and the full result of applying the
> > > > > user-supplied function to that. This is a pretty thin wrapper around
> > > > > the newish atomicModifyMutVar2# primop, which has replaced the less
> > > > > powerful atomicModifyMutVar#.
> > > > > atomicSwapIORef atomically installs a user-supplied value in an IORef
> > > > > and returns the old value. It is currently implemented using
> > > > > atomicModifyIORef2, but it can and should be reimplemented using its
> > > > > own, more efficient primop.
> > > > > I propose to add both of these functions to Data.IORef.
> > > > > David
> > > > > Libraries mailing list
> > > > > [hidden email]
> > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Add atomic IORef operations to Data.IORef

George Wilson
+1 for inclusion of these

On Sat, 16 Jan 2021 at 07:25, David Feuer <[hidden email]> wrote:

>
> The error handling situation for modification operations is somewhat deceptive. Unlike MVar operations, where the modifying thread can be fully responsible for exceptions, a thread can *try* to force the modified IORef value, but it may *actually* be forced by another thread if that thread gets there first. Someone using atomicModifyIORef2' should be very careful not to produce bottom as the new IORef value. Similarly, they must not use unsafePerformIO to produce the result if the IO in question must be performed in a particular thread.
>
> On Fri, Jan 15, 2021, 4:13 PM Alexey Kuleshevich <[hidden email]> wrote:
>>
>> Despite that this one is easy `atomicSwapIORef' ref !a = atomicSwapIORef ref a` I think it is important to include it. I also think `atomicWriteIORef'` should be added as well. Point is that most of the time in a concurrent setup it is the thread that does the IORef modification should be responsible for computing the value that is being written. This is important not only for performance but also for error handling.
>>
>> Alexey.
>>
>>
>> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>> On Saturday, January 16, 2021 12:01 AM, David Feuer <[hidden email]> wrote:
>>
>> > Cool. Do you also want a strict atomicSwapIORef'?
>> >
>> > On Fri, Jan 15, 2021 at 3:38 PM Alexey Kuleshevich [hidden email] wrote:
>> >
>> > > I totally agree with everything that you just said. Sorry, I should have said originally "-1 for adding JUST these lazy versions". As long as there are strict versions (whatever the names they might get, IMHO Lazy suffix is nice) and a warning on lazy versions about leaking memory, then I am 100% on board as well. Also +1 on not forcing the result.
>> > > Alexey.
>> > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>> > > On Friday, January 15, 2021 11:29 PM, David Feuer [hidden email] wrote:
>> > >
>> > > > I disagree. I believe we should offer both atomicModifyIORef2 and an
>> > > > atomicModifyIORef2'. The latter should force the new value in the
>> > > > IORef but, unlike atomicModifyIORef', should not force the returned
>> > > > value. Or if you and others prefer, we could offer a strict
>> > > > atomicModifyIORef and a lazy atomicModifyIORef2Lazy. As a Haskell
>> > > > programmer, I really don't want totally polymorphic values getting
>> > > > forced behind my back. It's actually possible to write an even lazier
>> > > > version that doesn't even force the function result pair, but I don't
>> > > > think that's a very useful idea.
>> > > > One other thing: the natural approach to atomicModifyIORef2' uses a
>> > > > "half-strict pair" type
>> > > > data HSPair a b = HSPair !a b
>> > > > atomicModifyIORef2' :: IORef a -> (a -> HSPair a b) -> IO (a, HSPair a b)
>> > > > I don't know to what extent users are willing to tolerate such an
>> > > > extra datatype.
>> > > > Side note: the peculiarly strict behavior of atomicModifyIORef' is a
>> > > > result of the poor design of the old atomicModifyMutVar# primop.
>> > > > On Fri, Jan 15, 2021 at 3:19 PM Alexey Kuleshevich [hidden email] wrote:
>> > > >
>> > > > > Both of these functions are lazy with respect to the new value being written into the IORef, which is a horrible default for atomic operations. That is why atomicModifyIORef is a source of memory leaks and terrible performance, which is also why atomicModifyIORef' is almost always used instead.
>> > > > > So +1 from me on adding strict versions of these functions that force new value to whnf, but -1 for adding these lazy versions as they are currently defined in GHC.IORef
>> > > > > Alexey.
>> > > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>> > > > > On Friday, January 15, 2021 11:05 PM, David Feuer [hidden email] wrote:
>> > > > >
>> > > > > > GHC.IORef currently exports
>> > > > > > atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
>> > > > > > atomicSwapIORef :: IORef a -> a -> IO a
>> > > > > > atomicModifyIORef2 is a lot like atomicModifyIORef, but it returns
>> > > > > > both the old value in the IORef and the full result of applying the
>> > > > > > user-supplied function to that. This is a pretty thin wrapper around
>> > > > > > the newish atomicModifyMutVar2# primop, which has replaced the less
>> > > > > > powerful atomicModifyMutVar#.
>> > > > > > atomicSwapIORef atomically installs a user-supplied value in an IORef
>> > > > > > and returns the old value. It is currently implemented using
>> > > > > > atomicModifyIORef2, but it can and should be reimplemented using its
>> > > > > > own, more efficient primop.
>> > > > > > I propose to add both of these functions to Data.IORef.
>> > > > > > David
>> > > > > > Libraries mailing list
>> > > > > > [hidden email]
>> > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries