packages feed

effectful-core 2.2.2.0 → 2.2.2.1

raw patch · 6 files changed

+132/−128 lines, 6 filesdep −effectful-coredep ~basePVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

Dependencies removed: effectful-core

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Effectful.Internal.Utils: data IORef' a
+ Effectful.Internal.Utils: data MVar' a
+ Effectful.Internal.Utils: eqThreadId :: ThreadId -> ThreadId -> Bool
+ Effectful.Internal.Utils: fromAny :: Any -> a
+ Effectful.Internal.Utils: modifyMVar' :: MVar' a -> (a -> IO (a, r)) -> IO r
+ Effectful.Internal.Utils: modifyMVar_' :: MVar' a -> (a -> IO a) -> IO ()
+ Effectful.Internal.Utils: newIORef' :: a -> IO (IORef' a)
+ Effectful.Internal.Utils: newMVar' :: a -> IO (MVar' a)
+ Effectful.Internal.Utils: readIORef' :: IORef' a -> IO a
+ Effectful.Internal.Utils: readMVar' :: MVar' a -> IO a
+ Effectful.Internal.Utils: toAny :: a -> Any
+ Effectful.Internal.Utils: toMVar' :: MVar a -> IO (MVar' a)
+ Effectful.Internal.Utils: type family Any :: k
+ Effectful.Internal.Utils: weakThreadId :: ThreadId -> Int
+ Effectful.Internal.Utils: writeIORef' :: IORef' a -> a -> IO ()

Files

CHANGELOG.md view
@@ -1,3 +1,6 @@+# effectful-core-2.2.2.1 (2023-01-12)+* Stop using the internal library because of bugs in `stack`.+ # effectful-core-2.2.2.0 (2023-01-11) * Add `withSeqEffToIO` and `withConcEffToIO` to `Effectful`. * Use strict `IORef` and `MVar` variants where appropriate.
+ cbits/utils.c view
@@ -0,0 +1,5 @@+// Correct implementation of ThreadId# equality for GHC < 9.+long effectful_eq_thread(void *tso1, void *tso2)+{+  return tso1 == tso2;+}
effectful-core.cabal view
@@ -1,7 +1,7 @@ cabal-version:      2.4 build-type:         Simple name:               effectful-core-version:            2.2.2.0+version:            2.2.2.1 license:            BSD-3-Clause license-file:       LICENSE category:           Control@@ -54,23 +54,11 @@                         TypeFamilies                         TypeOperators -library effectful-internal-utils-    import:          language--    build-depends:   base--    hs-source-dirs:  utils-    c-sources:       utils/utils.c--    exposed-modules: Effectful.Internal.Utils- library     import:         language      ghc-options:    -O2 -    build-depends:  effectful-internal-utils-     build-depends:    base                >= 4.13      && < 5                     , containers          >= 0.6                     , exceptions          >= 0.10.4@@ -81,6 +69,8 @@      hs-source-dirs:  src +    c-sources:       cbits/utils.c+     exposed-modules: Effectful                      Effectful.Dispatch.Dynamic                      Effectful.Dispatch.Static@@ -93,6 +83,7 @@                      Effectful.Internal.Env                      Effectful.Internal.Monad                      Effectful.Internal.Unlift+                     Effectful.Internal.Utils                      Effectful.NonDet                      Effectful.Prim                      Effectful.Reader.Dynamic@@ -103,5 +94,3 @@                      Effectful.Writer.Dynamic                      Effectful.Writer.Static.Local                      Effectful.Writer.Static.Shared--    reexported-modules: Effectful.Internal.Utils
+ src/Effectful/Internal/Utils.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# OPTIONS_HADDOCK not-home #-}+module Effectful.Internal.Utils+  ( weakThreadId+  , eqThreadId++  -- * Strict 'IORef'+  , IORef'+  , newIORef'+  , readIORef'+  , writeIORef'++  -- * Strict 'MVar'+  , MVar'+  , toMVar'+  , newMVar'+  , readMVar'+  , modifyMVar'+  , modifyMVar_'++  -- * Utils for 'Any'+  , Any+  , toAny+  , fromAny+  ) where++import Control.Concurrent.MVar+import Data.IORef+import Foreign.C.Types+import GHC.Conc.Sync (ThreadId(..))+import GHC.Exts (Addr#, Any, ThreadId#, unsafeCoerce#)+import Unsafe.Coerce (unsafeCoerce)++-- | Get an id of a thread that doesn't prevent its garbage collection.+weakThreadId :: ThreadId -> Int+weakThreadId (ThreadId t#) = fromIntegral $ rts_getThreadId (threadIdToAddr# t#)++foreign import ccall unsafe "rts_getThreadId"+#if __GLASGOW_HASKELL__ >= 904+  -- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6163+  rts_getThreadId :: Addr# -> CULLong+#elif __GLASGOW_HASKELL__ >= 900+  -- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/1254+  rts_getThreadId :: Addr# -> CLong+#else+  rts_getThreadId :: Addr# -> CInt+#endif++-- | 'Eq' instance for 'ThreadId' is broken in GHC < 9, see+-- https://gitlab.haskell.org/ghc/ghc/-/issues/16761 for more info.+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++-- Note: FFI imports take Addr# instead of ThreadId# because of+-- https://gitlab.haskell.org/ghc/ghc/-/issues/8281, which would prevent loading+-- effectful-core into GHCi.+--+-- Previous workaround was to use an internal library with just this module, but+-- this is not viable because of bugs in stack (sigh).+--+-- The coercion is fine because GHC represents ThreadId# as a pointer.+threadIdToAddr# :: ThreadId# -> Addr#+threadIdToAddr# = unsafeCoerce#++----------------------------------------++-- | A strict variant of 'IORef'.+newtype IORef' a = IORef' (IORef a)++newIORef' :: a -> IO (IORef' a)+newIORef' a = a `seq` (IORef' <$> newIORef a)++readIORef' :: IORef' a -> IO a+readIORef' (IORef' var) = readIORef var++writeIORef' :: IORef' a -> a -> IO ()+writeIORef' (IORef' var) a = a `seq` writeIORef var a++----------------------------------------++-- | A strict variant of 'MVar'.+newtype MVar' a = MVar' (MVar a)++toMVar' :: MVar a -> IO (MVar' a)+toMVar' var = do+  let var' = MVar' var+  modifyMVar_' var' pure+  pure var'++newMVar' :: a -> IO (MVar' a)+newMVar' a = a `seq` (MVar' <$> newMVar a)++readMVar' :: MVar' a -> IO a+readMVar' (MVar' var) = readMVar var++modifyMVar' :: MVar' a -> (a -> IO (a, r)) -> IO r+modifyMVar' (MVar' var) action = modifyMVar var $ \a0 -> do+  (a, r) <- action a0+  a `seq` pure (a, r)+{-# INLINE modifyMVar' #-}++modifyMVar_' :: MVar' a -> (a -> IO a) -> IO ()+modifyMVar_' (MVar' var) action = modifyMVar_ var $ \a0 -> do+  a <- action a0+  a `seq` pure a+{-# INLINE modifyMVar_' #-}++----------------------------------------++toAny :: a -> Any+toAny = unsafeCoerce++fromAny :: Any -> a+fromAny = unsafeCoerce
− utils/Effectful/Internal/Utils.hs
@@ -1,108 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE UnliftedFFITypes #-}-{-# OPTIONS_HADDOCK not-home #-}-module Effectful.Internal.Utils-  ( weakThreadId-  , eqThreadId--  -- * Strict 'IORef'-  , IORef'-  , newIORef'-  , readIORef'-  , writeIORef'--  -- * Strict 'MVar'-  , MVar'-  , toMVar'-  , newMVar'-  , readMVar'-  , modifyMVar'-  , modifyMVar_'--  -- * Utils for 'Any'-  , Any-  , toAny-  , fromAny-  ) where--import Control.Concurrent.MVar-import Data.IORef-import Foreign.C.Types-import GHC.Conc.Sync (ThreadId(..))-import GHC.Exts (Any, ThreadId#)-import Unsafe.Coerce (unsafeCoerce)---- | Get an id of a thread that doesn't prevent its garbage collection.-weakThreadId :: ThreadId -> Int-weakThreadId (ThreadId t#) = fromIntegral $ rts_getThreadId t#--foreign import ccall unsafe "rts_getThreadId"-#if __GLASGOW_HASKELL__ >= 904-  -- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6163-  rts_getThreadId :: ThreadId# -> CULLong-#elif __GLASGOW_HASKELL__ >= 900-  -- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/1254-  rts_getThreadId :: ThreadId# -> CLong-#else-  rts_getThreadId :: ThreadId# -> CInt-#endif---- | 'Eq' instance for 'ThreadId' is broken in GHC < 9, see--- https://gitlab.haskell.org/ghc/ghc/-/issues/16761 for more info.-eqThreadId :: ThreadId -> ThreadId -> Bool-eqThreadId (ThreadId t1#) (ThreadId t2#) = eq_thread t1# t2# == 1--foreign import ccall unsafe "effectful_eq_thread"-  eq_thread :: ThreadId# -> ThreadId# -> CLong---------------------------------------------- | A strict variant of 'IORef'.-newtype IORef' a = IORef' (IORef a)--newIORef' :: a -> IO (IORef' a)-newIORef' a = a `seq` (IORef' <$> newIORef a)--readIORef' :: IORef' a -> IO a-readIORef' (IORef' var) = readIORef var--writeIORef' :: IORef' a -> a -> IO ()-writeIORef' (IORef' var) a = a `seq` writeIORef var a---------------------------------------------- | A strict variant of 'MVar'.-newtype MVar' a = MVar' (MVar a)--toMVar' :: MVar a -> IO (MVar' a)-toMVar' var = do-  let var' = MVar' var-  modifyMVar_' var' pure-  pure var'--newMVar' :: a -> IO (MVar' a)-newMVar' a = a `seq` (MVar' <$> newMVar a)--readMVar' :: MVar' a -> IO a-readMVar' (MVar' var) = readMVar var--modifyMVar' :: MVar' a -> (a -> IO (a, r)) -> IO r-modifyMVar' (MVar' var) action = modifyMVar var $ \a0 -> do-  (a, r) <- action a0-  a `seq` pure (a, r)-{-# INLINE modifyMVar' #-}--modifyMVar_' :: MVar' a -> (a -> IO a) -> IO ()-modifyMVar_' (MVar' var) action = modifyMVar_ var $ \a0 -> do-  a <- action a0-  a `seq` pure a-{-# INLINE modifyMVar_' #-}--------------------------------------------toAny :: a -> Any-toAny = unsafeCoerce--fromAny :: Any -> a-fromAny = unsafeCoerce
− utils/utils.c
@@ -1,5 +0,0 @@-// Correct implementation of ThreadId# equality for GHC < 9.-long effectful_eq_thread(void *tso1, void *tso2)-{-  return tso1 == tso2;-}