{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
{-# OPTIONS_HADDOCK not-home #-}
module Effectful.Internal.Utils
( inlineBracket
, weakThreadId
, eqThreadId
, Any
, toAny
, fromAny
, Unique
, newUnique
, thawCallStack
, growCapacity
) where
import Control.Exception
import Data.Primitive.ByteArray
import GHC.Conc.Sync (ThreadId(..))
import GHC.Exts (Any, RealWorld)
import GHC.Stack.Types (CallStack(..))
import Unsafe.Coerce (unsafeCoerce)
#if MIN_VERSION_base(4,19,0)
import GHC.Conc.Sync (fromThreadId)
#else
import GHC.Exts (Addr#, ThreadId#, unsafeCoerce#)
#if __GLASGOW_HASKELL__ >= 904
import Data.Word
#else
import Foreign.C.Types
#endif
#endif
inlineBracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
inlineBracket :: forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
inlineBracket IO a
before a -> IO b
after a -> IO c
action = ((forall a. IO a -> IO a) -> IO c) -> IO c
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask (((forall a. IO a -> IO a) -> IO c) -> IO c)
-> ((forall a. IO a -> IO a) -> IO c) -> IO c
forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
unmask -> do
a
a <- IO a
before
c
r <- IO c -> IO c
forall a. IO a -> IO a
unmask (a -> IO c
action a
a) IO c -> IO b -> IO c
forall a b. IO a -> IO b -> IO a
`onException` a -> IO b
after a
a
b
_ <- a -> IO b
after a
a
c -> IO c
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure c
r
{-# INLINE inlineBracket #-}
weakThreadId :: ThreadId -> Int
#if MIN_VERSION_base(4,19,0)
weakThreadId :: ThreadId -> Int
weakThreadId = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int) -> (ThreadId -> Word64) -> ThreadId -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ThreadId -> Word64
fromThreadId
#else
weakThreadId (ThreadId t#) = fromIntegral $ rts_getThreadId (threadIdToAddr# t#)
foreign import ccall unsafe "rts_getThreadId"
#if __GLASGOW_HASKELL__ >= 904
rts_getThreadId :: Addr# -> Word64
#elif __GLASGOW_HASKELL__ >= 900
rts_getThreadId :: Addr# -> CLong
#else
rts_getThreadId :: Addr# -> CInt
#endif
threadIdToAddr# :: ThreadId# -> Addr#
threadIdToAddr# = unsafeCoerce#
#endif
#if __GLASGOW_HASKELL__ < 900
eqThreadId :: ThreadId -> ThreadId -> Bool
eqThreadId (ThreadId t1#) (ThreadId t2#) =
eq_thread (threadIdToAddr# t1#) (threadIdToAddr# t2#) == 1
foreign import ccall unsafe "effectful_eq_thread"
eq_thread :: Addr# -> Addr# -> CLong
#else
eqThreadId :: ThreadId -> ThreadId -> Bool
eqThreadId :: ThreadId -> ThreadId -> Bool
eqThreadId = ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
(==)
#endif
toAny :: a -> Any
toAny :: forall a. a -> Any
toAny = a -> Any
forall a b. a -> b
unsafeCoerce
fromAny :: Any -> a
fromAny :: forall a. Any -> a
fromAny = Any -> a
forall a b. a -> b
unsafeCoerce
newtype Unique = Unique (MutableByteArray RealWorld)
instance Eq Unique where
Unique MutableByteArray RealWorld
a == :: Unique -> Unique -> Bool
== Unique MutableByteArray RealWorld
b = MutableByteArray RealWorld -> MutableByteArray RealWorld -> Bool
forall s. MutableByteArray s -> MutableByteArray s -> Bool
sameMutableByteArray MutableByteArray RealWorld
a MutableByteArray RealWorld
b
newUnique :: IO Unique
newUnique :: IO Unique
newUnique = MutableByteArray RealWorld -> Unique
Unique (MutableByteArray RealWorld -> Unique)
-> IO (MutableByteArray RealWorld) -> IO Unique
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> IO (MutableByteArray (PrimState IO))
forall (m :: Type -> Type).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
0
thawCallStack :: CallStack -> CallStack
thawCallStack :: CallStack -> CallStack
thawCallStack = \case
FreezeCallStack CallStack
cs -> CallStack
cs
CallStack
cs -> CallStack
cs
growCapacity :: Int -> Int
growCapacity :: Int -> Int
growCapacity Int
n = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
forall a. Integral a => a -> a -> a
quot (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
3) Int
2