1
1
{-# LANGUAGE BangPatterns #-}
2
+ {-# LANGUAGE CPP #-}
2
3
{-# LANGUAGE FlexibleInstances #-}
3
4
{-# LANGUAGE FunctionalDependencies #-}
4
5
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -143,6 +144,10 @@ import Data.STRef
143
144
import Foreign.Storable
144
145
import System.Random
145
146
import System.Random.Internal
147
+ #if __GLASGOW_HASKELL__ >= 808
148
+ import GHC.IORef (atomicModifyIORef2Lazy )
149
+ #endif
150
+
146
151
147
152
-- $introduction
148
153
--
@@ -414,7 +419,7 @@ instance (RandomGen g, MonadIO m) => FrozenGen (AtomicGen g) m where
414
419
type MutableGen (AtomicGen g ) m = AtomicGenM g
415
420
freezeGen = fmap AtomicGen . liftIO . readIORef . unAtomicGenM
416
421
modifyGen (AtomicGenM ioRef) f =
417
- liftIO $ atomicModifyIORef' ioRef $ \ g ->
422
+ liftIO $ atomicModifyIORefHS ioRef $ \ g ->
418
423
case f (AtomicGen g) of
419
424
(a, AtomicGen g') -> (g', a)
420
425
{-# INLINE modifyGen #-}
@@ -436,11 +441,27 @@ instance (RandomGen g, MonadIO m) => ThawedGen (AtomicGen g) m where
436
441
-- @since 1.2.0
437
442
applyAtomicGen :: MonadIO m => (g -> (a , g )) -> AtomicGenM g -> m a
438
443
applyAtomicGen op (AtomicGenM gVar) =
439
- liftIO $ atomicModifyIORef' gVar $ \ g ->
444
+ liftIO $ atomicModifyIORefHS gVar $ \ g ->
440
445
case op g of
441
446
(a, g') -> (g', a)
442
447
{-# INLINE applyAtomicGen #-}
443
448
449
+ -- HalfStrict version of atomicModifyIORef, i.e. strict in the modifcation of the contents
450
+ -- of the IORef, but not in the result produced.
451
+ atomicModifyIORefHS :: IORef a -> (a -> (a , b )) -> IO b
452
+ atomicModifyIORefHS ref f = do
453
+ #if __GLASGOW_HASKELL__ >= 808
454
+ (_old, (_new, res)) <- atomicModifyIORef2Lazy ref $ \ old ->
455
+ case f old of
456
+ r@ (! _new, _res) -> r
457
+ pure res
458
+ #else
459
+ atomicModifyIORef ref $ \ old ->
460
+ case f old of
461
+ r@ (! _new, _res) -> r
462
+ #endif
463
+ {-# INLINE atomicModifyIORefHS #-}
464
+
444
465
-- | Wraps an 'IORef' that holds a pure pseudo-random number generator.
445
466
--
446
467
-- * 'IOGenM' is safe in the presence of exceptions, but not concurrency.
@@ -526,7 +547,7 @@ applyIOGen :: MonadIO m => (g -> (a, g)) -> IOGenM g -> m a
526
547
applyIOGen f (IOGenM ref) = liftIO $ do
527
548
g <- readIORef ref
528
549
case f g of
529
- (! a, ! g') -> a <$ writeIORef ref g'
550
+ (a, ! g') -> a <$ writeIORef ref g'
530
551
{-# INLINE applyIOGen #-}
531
552
532
553
-- | Wraps an 'STRef' that holds a pure pseudo-random number generator.
@@ -600,7 +621,7 @@ applySTGen :: (g -> (a, g)) -> STGenM g s -> ST s a
600
621
applySTGen f (STGenM ref) = do
601
622
g <- readSTRef ref
602
623
case f g of
603
- (! a, ! g') -> a <$ writeSTRef ref g'
624
+ (a, ! g') -> a <$ writeSTRef ref g'
604
625
{-# INLINE applySTGen #-}
605
626
606
627
-- | Runs a monadic generating action in the `ST` monad using a pure
0 commit comments