1{-# LANGUAGE UnboxedTuples #-}
6-- Module : Streamly.Internal.Data.IORef.Prim
7-- Copyright : (c) 2019 Composewell Technologies
10-- Maintainer : streamly@composewell.com
11-- Stability : experimental
14-- A mutable variable in a mutation capable monad (IO) holding a 'Prim'
15-- value. This allows fast modification because of unboxed storage.
17-- = Multithread Consistency Notes
19-- In general, any value that straddles a machine word cannot be guaranteed to
20-- be consistently read from another thread without a lock. GHC heap objects
21-- are always machine word aligned, therefore, a 'IORef' is also word aligned.
22-- On a 64-bit platform, writing a 64-bit aligned type from one thread and
23-- reading it from another thread should give consistent old or new value. The
24-- same holds true for 32-bit values on a 32-bit platform.
26module Streamly.Internal.Data.IORef.Prim
43import Control.Monad.Primitive (primitive_)
44import Data.Primitive.Types (Prim, sizeOf#, readByteArray#, writeByteArray#)
45import GHC.Exts (MutableByteArray#, newByteArray#, RealWorld)
48-- | An 'IORef' holds a single 'Prim' value.
49data IORef a = IORef (MutableByteArray# RealWorld)
51-- | Create a new 'IORef'.
54{-# INLINE newIORef #-}
55newIORef :: forall a. Prim a => a -> IO (IORef a)
56newIORef x = IO (\s# ->
57 case newByteArray# (sizeOf# (undefined :: a)) s# of
59 case writeByteArray# arr# 0# x s1# of
60 s2# -> (# s2#, IORef arr# #)
63-- | Write a value to an 'IORef'.
66{-# INLINE writeIORef #-}
67writeIORef :: Prim a => IORef a -> a -> IO ()
68writeIORef (IORef arr#) x = primitive_ (writeByteArray# arr# 0# x)
70-- | Read a value from an 'IORef'.
73{-# INLINE readIORef #-}
74readIORef :: Prim a => IORef a -> IO a
75readIORef (IORef arr#) = IO (readByteArray# arr# 0#)
77-- | Modify the value of an 'IORef' using a function with strict application.
80{-# INLINE modifyIORef' #-}
81modifyIORef' :: Prim a => IORef a -> (a -> a) -> IO ()
82modifyIORef' (IORef arr#) g = primitive_ $ \s# ->
83 case readByteArray# arr# 0# s# of
84 (# s'#, a #) -> let a' = g a in a' `seq` writeByteArray# arr# 0# a' s'#
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list