{-# LANGUAGE MagicHash #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_HADDOCK not-home #-}
module Effectful.Internal.Unlift
(
UnliftStrategy(..)
, Persistence(..)
, Limit(..)
, ephemeralConcLimitedUnlift
, ephemeralConcUnlimitedUnlift
, persistentConcUnlift
, persistentConcSingleUnlift
, persistentConcUnlifts
, persistentConcSingleUnlifts
) where
import Control.Concurrent
import Control.Concurrent.MVar.Strict qualified as S
import Control.Monad
import Data.Coerce
import Data.Word
import GHC.Conc.Sync (ThreadId(..))
import GHC.Exts (mkWeak#, mkWeakNoFinalizer#)
import GHC.Generics (Generic)
import GHC.IO (IO(..))
import GHC.Stack (HasCallStack)
import GHC.Weak (Weak(..))
import System.Mem.Weak (deRefWeak)
import Effectful.Internal.Env
import Effectful.Internal.Utils
import Effectful.Internal.Utils.Word64Map qualified as M
data UnliftStrategy
= SeqUnlift
| SeqForkUnlift
| ConcUnlift !Persistence !Limit
deriving stock (UnliftStrategy -> UnliftStrategy -> Bool
(UnliftStrategy -> UnliftStrategy -> Bool)
-> (UnliftStrategy -> UnliftStrategy -> Bool) -> Eq UnliftStrategy
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: UnliftStrategy -> UnliftStrategy -> Bool
== :: UnliftStrategy -> UnliftStrategy -> Bool
$c/= :: UnliftStrategy -> UnliftStrategy -> Bool
/= :: UnliftStrategy -> UnliftStrategy -> Bool
Eq, (forall x. UnliftStrategy -> Rep UnliftStrategy x)
-> (forall x. Rep UnliftStrategy x -> UnliftStrategy)
-> Generic UnliftStrategy
forall x. Rep UnliftStrategy x -> UnliftStrategy
forall x. UnliftStrategy -> Rep UnliftStrategy x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. UnliftStrategy -> Rep UnliftStrategy x
from :: forall x. UnliftStrategy -> Rep UnliftStrategy x
$cto :: forall x. Rep UnliftStrategy x -> UnliftStrategy
to :: forall x. Rep UnliftStrategy x -> UnliftStrategy
Generic, Eq UnliftStrategy
Eq UnliftStrategy =>
(UnliftStrategy -> UnliftStrategy -> Ordering)
-> (UnliftStrategy -> UnliftStrategy -> Bool)
-> (UnliftStrategy -> UnliftStrategy -> Bool)
-> (UnliftStrategy -> UnliftStrategy -> Bool)
-> (UnliftStrategy -> UnliftStrategy -> Bool)
-> (UnliftStrategy -> UnliftStrategy -> UnliftStrategy)
-> (UnliftStrategy -> UnliftStrategy -> UnliftStrategy)
-> Ord UnliftStrategy
UnliftStrategy -> UnliftStrategy -> Bool
UnliftStrategy -> UnliftStrategy -> Ordering
UnliftStrategy -> UnliftStrategy -> UnliftStrategy
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: UnliftStrategy -> UnliftStrategy -> Ordering
compare :: UnliftStrategy -> UnliftStrategy -> Ordering
$c< :: UnliftStrategy -> UnliftStrategy -> Bool
< :: UnliftStrategy -> UnliftStrategy -> Bool
$c<= :: UnliftStrategy -> UnliftStrategy -> Bool
<= :: UnliftStrategy -> UnliftStrategy -> Bool
$c> :: UnliftStrategy -> UnliftStrategy -> Bool
> :: UnliftStrategy -> UnliftStrategy -> Bool
$c>= :: UnliftStrategy -> UnliftStrategy -> Bool
>= :: UnliftStrategy -> UnliftStrategy -> Bool
$cmax :: UnliftStrategy -> UnliftStrategy -> UnliftStrategy
max :: UnliftStrategy -> UnliftStrategy -> UnliftStrategy
$cmin :: UnliftStrategy -> UnliftStrategy -> UnliftStrategy
min :: UnliftStrategy -> UnliftStrategy -> UnliftStrategy
Ord, Int -> UnliftStrategy -> ShowS
[UnliftStrategy] -> ShowS
UnliftStrategy -> String
(Int -> UnliftStrategy -> ShowS)
-> (UnliftStrategy -> String)
-> ([UnliftStrategy] -> ShowS)
-> Show UnliftStrategy
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> UnliftStrategy -> ShowS
showsPrec :: Int -> UnliftStrategy -> ShowS
$cshow :: UnliftStrategy -> String
show :: UnliftStrategy -> String
$cshowList :: [UnliftStrategy] -> ShowS
showList :: [UnliftStrategy] -> ShowS
Show)
data Persistence
= Ephemeral
| Persistent
deriving stock (Persistence -> Persistence -> Bool
(Persistence -> Persistence -> Bool)
-> (Persistence -> Persistence -> Bool) -> Eq Persistence
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Persistence -> Persistence -> Bool
== :: Persistence -> Persistence -> Bool
$c/= :: Persistence -> Persistence -> Bool
/= :: Persistence -> Persistence -> Bool
Eq, (forall x. Persistence -> Rep Persistence x)
-> (forall x. Rep Persistence x -> Persistence)
-> Generic Persistence
forall x. Rep Persistence x -> Persistence
forall x. Persistence -> Rep Persistence x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Persistence -> Rep Persistence x
from :: forall x. Persistence -> Rep Persistence x
$cto :: forall x. Rep Persistence x -> Persistence
to :: forall x. Rep Persistence x -> Persistence
Generic, Eq Persistence
Eq Persistence =>
(Persistence -> Persistence -> Ordering)
-> (Persistence -> Persistence -> Bool)
-> (Persistence -> Persistence -> Bool)
-> (Persistence -> Persistence -> Bool)
-> (Persistence -> Persistence -> Bool)
-> (Persistence -> Persistence -> Persistence)
-> (Persistence -> Persistence -> Persistence)
-> Ord Persistence
Persistence -> Persistence -> Bool
Persistence -> Persistence -> Ordering
Persistence -> Persistence -> Persistence
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Persistence -> Persistence -> Ordering
compare :: Persistence -> Persistence -> Ordering
$c< :: Persistence -> Persistence -> Bool
< :: Persistence -> Persistence -> Bool
$c<= :: Persistence -> Persistence -> Bool
<= :: Persistence -> Persistence -> Bool
$c> :: Persistence -> Persistence -> Bool
> :: Persistence -> Persistence -> Bool
$c>= :: Persistence -> Persistence -> Bool
>= :: Persistence -> Persistence -> Bool
$cmax :: Persistence -> Persistence -> Persistence
max :: Persistence -> Persistence -> Persistence
$cmin :: Persistence -> Persistence -> Persistence
min :: Persistence -> Persistence -> Persistence
Ord, Int -> Persistence -> ShowS
[Persistence] -> ShowS
Persistence -> String
(Int -> Persistence -> ShowS)
-> (Persistence -> String)
-> ([Persistence] -> ShowS)
-> Show Persistence
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Persistence -> ShowS
showsPrec :: Int -> Persistence -> ShowS
$cshow :: Persistence -> String
show :: Persistence -> String
$cshowList :: [Persistence] -> ShowS
showList :: [Persistence] -> ShowS
Show)
data Limit
= Limited !Int
| Unlimited
deriving stock (Limit -> Limit -> Bool
(Limit -> Limit -> Bool) -> (Limit -> Limit -> Bool) -> Eq Limit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Limit -> Limit -> Bool
== :: Limit -> Limit -> Bool
$c/= :: Limit -> Limit -> Bool
/= :: Limit -> Limit -> Bool
Eq, (forall x. Limit -> Rep Limit x)
-> (forall x. Rep Limit x -> Limit) -> Generic Limit
forall x. Rep Limit x -> Limit
forall x. Limit -> Rep Limit x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Limit -> Rep Limit x
from :: forall x. Limit -> Rep Limit x
$cto :: forall x. Rep Limit x -> Limit
to :: forall x. Rep Limit x -> Limit
Generic, Eq Limit
Eq Limit =>
(Limit -> Limit -> Ordering)
-> (Limit -> Limit -> Bool)
-> (Limit -> Limit -> Bool)
-> (Limit -> Limit -> Bool)
-> (Limit -> Limit -> Bool)
-> (Limit -> Limit -> Limit)
-> (Limit -> Limit -> Limit)
-> Ord Limit
Limit -> Limit -> Bool
Limit -> Limit -> Ordering
Limit -> Limit -> Limit
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Limit -> Limit -> Ordering
compare :: Limit -> Limit -> Ordering
$c< :: Limit -> Limit -> Bool
< :: Limit -> Limit -> Bool
$c<= :: Limit -> Limit -> Bool
<= :: Limit -> Limit -> Bool
$c> :: Limit -> Limit -> Bool
> :: Limit -> Limit -> Bool
$c>= :: Limit -> Limit -> Bool
>= :: Limit -> Limit -> Bool
$cmax :: Limit -> Limit -> Limit
max :: Limit -> Limit -> Limit
$cmin :: Limit -> Limit -> Limit
min :: Limit -> Limit -> Limit
Ord, Int -> Limit -> ShowS
[Limit] -> ShowS
Limit -> String
(Int -> Limit -> ShowS)
-> (Limit -> String) -> ([Limit] -> ShowS) -> Show Limit
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Limit -> ShowS
showsPrec :: Int -> Limit -> ShowS
$cshow :: Limit -> String
show :: Limit -> String
$cshowList :: [Limit] -> ShowS
showList :: [Limit] -> ShowS
Show)
ephemeralConcLimitedUnlift
:: (HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r))
=> Env es
-> Int
-> ((forall r. effEs r -> IO r) -> IO a)
-> IO a
ephemeralConcLimitedUnlift :: forall (effEs :: Type -> Type) (es :: [Effect]) a.
(HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r)) =>
Env es -> Int -> ((forall r. effEs r -> IO r) -> IO a) -> IO a
ephemeralConcLimitedUnlift Env es
es0 Int
uses (forall r. effEs r -> IO r) -> IO a
k = do
Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
unless (Int
uses Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
forall a. HasCallStack => String -> a
error (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid number of uses: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
uses
ThreadId
tid0 <- IO ThreadId
myThreadId
Env es
esTemplate <- Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
es0
MVar Int
mvUses <- Int -> IO (MVar Int)
forall a. a -> IO (MVar a)
S.newMVar Int
uses
let getEs :: IO (Env es)
getEs = IO ThreadId
myThreadId IO ThreadId -> (ThreadId -> IO (Env es)) -> IO (Env es)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ThreadId
tid | ThreadId
tid0 ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
== ThreadId
tid -> Env es -> IO (Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Env es
es0
ThreadId
_ -> MVar Int -> (Int -> IO (Int, Env es)) -> IO (Env es)
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
S.modifyMVar MVar Int
mvUses ((Int -> IO (Int, Env es)) -> IO (Env es))
-> (Int -> IO (Int, Env es)) -> IO (Env es)
forall a b. (a -> b) -> a -> b
$ \case
Int
0 -> String -> IO (Int, Env es)
forall a. HasCallStack => String -> a
error
(String -> IO (Int, Env es)) -> String -> IO (Int, Env es)
forall a b. (a -> b) -> a -> b
$ String
"Number of permitted calls (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
uses String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") to the unlifting "
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"function in other threads was exceeded. Please increase the limit "
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"or use the unlimited variant."
Int
1 -> (Int, Env es) -> IO (Int, Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Int
0, Env es
esTemplate)
Int
n -> do
Env es
es <- Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
esTemplate
(Int, Env es) -> IO (Int, Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1, Env es
es)
(forall r. effEs r -> IO r) -> IO a
k ((forall r. effEs r -> IO r) -> IO a)
-> (forall r. effEs r -> IO r) -> IO a
forall a b. (a -> b) -> a -> b
$ \effEs r
action -> effEs r -> Env es -> IO r
forall a b. Coercible a b => a -> b
coerce effEs r
action (Env es -> IO r) -> IO (Env es) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es)
getEs
{-# INLINE ephemeralConcLimitedUnlift #-}
ephemeralConcUnlimitedUnlift
:: (HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r))
=> Env es
-> ((forall r. effEs r -> IO r) -> IO a)
-> IO a
ephemeralConcUnlimitedUnlift :: forall (effEs :: Type -> Type) (es :: [Effect]) a.
(HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r)) =>
Env es -> ((forall r. effEs r -> IO r) -> IO a) -> IO a
ephemeralConcUnlimitedUnlift Env es
es0 (forall r. effEs r -> IO r) -> IO a
k = do
ThreadId
tid0 <- IO ThreadId
myThreadId
Env es
esTemplate <- Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
es0
let getEs :: IO (Env es)
getEs = IO ThreadId
myThreadId IO ThreadId -> (ThreadId -> IO (Env es)) -> IO (Env es)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ThreadId
tid | ThreadId
tid0 ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
== ThreadId
tid -> Env es -> IO (Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Env es
es0
ThreadId
_ -> Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
esTemplate
(forall r. effEs r -> IO r) -> IO a
k ((forall r. effEs r -> IO r) -> IO a)
-> (forall r. effEs r -> IO r) -> IO a
forall a b. (a -> b) -> a -> b
$ \effEs r
action -> effEs r -> Env es -> IO r
forall a b. Coercible a b => a -> b
coerce effEs r
action (Env es -> IO r) -> IO (Env es) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es)
getEs
{-# INLINE ephemeralConcUnlimitedUnlift #-}
persistentConcUnlift
:: (HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r))
=> Env es
-> Bool
-> Int
-> ((forall r. effEs r -> IO r) -> IO a)
-> IO a
persistentConcUnlift :: forall (effEs :: Type -> Type) (es :: [Effect]) a.
(HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r)) =>
Env es
-> Bool -> Int -> ((forall r. effEs r -> IO r) -> IO a) -> IO a
persistentConcUnlift Env es
es0 Bool
cleanUp Int
threads (forall r. effEs r -> IO r) -> IO a
k = do
Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
unless (Int
threads Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
forall a. HasCallStack => String -> a
error (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid number of threads: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
threads
ThreadId
tid0 <- IO ThreadId
myThreadId
Env es
esTemplate <- Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
es0
MVar (ThreadEntries (Env es))
mvEntries <- ThreadEntries (Env es) -> IO (MVar (ThreadEntries (Env es)))
forall a. a -> IO (MVar a)
S.newMVar (ThreadEntries (Env es) -> IO (MVar (ThreadEntries (Env es))))
-> ThreadEntries (Env es) -> IO (MVar (ThreadEntries (Env es)))
forall a b. (a -> b) -> a -> b
$ Int -> Word64Map (Weak (Env es)) -> ThreadEntries (Env es)
forall a. Int -> Word64Map (Weak a) -> ThreadEntries a
ThreadEntries Int
threads Word64Map (Weak (Env es))
forall a. Word64Map a
M.empty
let getEs :: IO (Env es)
getEs = IO ThreadId
myThreadId IO ThreadId -> (ThreadId -> IO (Env es)) -> IO (Env es)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ThreadId
tid | ThreadId
tid0 ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
== ThreadId
tid -> Env es -> IO (Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Env es
es0
ThreadId
tid -> do
ThreadEntries (Env es)
te0 <- MVar (ThreadEntries (Env es)) -> IO (ThreadEntries (Env es))
forall a. MVar a -> IO a
S.readMVar MVar (ThreadEntries (Env es))
mvEntries
let wkTid :: Word64
wkTid = ThreadId -> Word64
weakThreadId ThreadId
tid
case Word64
wkTid Word64 -> Word64Map (Weak (Env es)) -> Maybe (Weak (Env es))
forall a. Word64 -> Word64Map a -> Maybe a
`M.lookup` ThreadEntries (Env es)
te0.entries of
Just Weak (Env es)
wkEs -> Weak (Env es) -> IO (Env es)
forall a. HasCallStack => Weak a -> IO a
getWkTidEnv Weak (Env es)
wkEs
Maybe (Weak (Env es))
Nothing -> MVar (ThreadEntries (Env es))
-> (ThreadEntries (Env es) -> IO (ThreadEntries (Env es), Env es))
-> IO (Env es)
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
S.modifyMVar MVar (ThreadEntries (Env es))
mvEntries ((ThreadEntries (Env es) -> IO (ThreadEntries (Env es), Env es))
-> IO (Env es))
-> (ThreadEntries (Env es) -> IO (ThreadEntries (Env es), Env es))
-> IO (Env es)
forall a b. (a -> b) -> a -> b
$ \ThreadEntries (Env es)
te -> case ThreadEntries (Env es)
te.capacity of
Int
0 -> Int -> IO (ThreadEntries (Env es), Env es)
forall a. HasCallStack => Int -> a
noCapacityError Int
threads
Int
1 -> do
Weak (Env es)
wkTidEs <- ThreadId
-> Word64
-> Env es
-> MVar (ThreadEntries (Env es))
-> Bool
-> IO (Weak (Env es))
forall a.
ThreadId
-> Word64 -> a -> MVar (ThreadEntries a) -> Bool -> IO (Weak a)
mkWeakThreadIdEnv ThreadId
tid Word64
wkTid Env es
esTemplate MVar (ThreadEntries (Env es))
mvEntries Bool
cleanUp
let newEntries :: ThreadEntries (Env es)
newEntries = ThreadEntries
{ $sel:capacity:ThreadEntries :: Int
capacity = ThreadEntries (Env es)
te.capacity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
, $sel:entries:ThreadEntries :: Word64Map (Weak (Env es))
entries = Word64
-> Weak (Env es)
-> Word64Map (Weak (Env es))
-> Word64Map (Weak (Env es))
forall a. Word64 -> a -> Word64Map a -> Word64Map a
M.insert Word64
wkTid Weak (Env es)
wkTidEs ThreadEntries (Env es)
te.entries
}
(ThreadEntries (Env es), Env es)
-> IO (ThreadEntries (Env es), Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (ThreadEntries (Env es)
newEntries, Env es
esTemplate)
Int
_ -> do
Env es
es <- Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
esTemplate
Weak (Env es)
wkTidEs <- ThreadId
-> Word64
-> Env es
-> MVar (ThreadEntries (Env es))
-> Bool
-> IO (Weak (Env es))
forall a.
ThreadId
-> Word64 -> a -> MVar (ThreadEntries a) -> Bool -> IO (Weak a)
mkWeakThreadIdEnv ThreadId
tid Word64
wkTid Env es
es MVar (ThreadEntries (Env es))
mvEntries Bool
cleanUp
let newEntries :: ThreadEntries (Env es)
newEntries = ThreadEntries
{ $sel:capacity:ThreadEntries :: Int
capacity = ThreadEntries (Env es)
te.capacity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
, $sel:entries:ThreadEntries :: Word64Map (Weak (Env es))
entries = Word64
-> Weak (Env es)
-> Word64Map (Weak (Env es))
-> Word64Map (Weak (Env es))
forall a. Word64 -> a -> Word64Map a -> Word64Map a
M.insert Word64
wkTid Weak (Env es)
wkTidEs ThreadEntries (Env es)
te.entries
}
(ThreadEntries (Env es), Env es)
-> IO (ThreadEntries (Env es), Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (ThreadEntries (Env es)
newEntries, Env es
es)
(forall r. effEs r -> IO r) -> IO a
k ((forall r. effEs r -> IO r) -> IO a)
-> (forall r. effEs r -> IO r) -> IO a
forall a b. (a -> b) -> a -> b
$ \effEs r
action -> effEs r -> Env es -> IO r
forall a b. Coercible a b => a -> b
coerce effEs r
action (Env es -> IO r) -> IO (Env es) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es)
getEs
{-# INLINE persistentConcUnlift #-}
persistentConcSingleUnlift
:: ( HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r))
=> Env es
-> ((forall r. effEs r -> IO r) -> IO a)
-> IO a
persistentConcSingleUnlift :: forall (effEs :: Type -> Type) (es :: [Effect]) a.
(HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r)) =>
Env es -> ((forall r. effEs r -> IO r) -> IO a) -> IO a
persistentConcSingleUnlift Env es
es0 (forall r. effEs r -> IO r) -> IO a
k = do
ThreadId
tid0 <- IO ThreadId
myThreadId
Env es
es <- Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
es0
MVar Word64
mvWeakTid <- Word64 -> IO (MVar Word64)
forall a. a -> IO (MVar a)
S.newMVar Word64
0
let getEs :: IO (Env es)
getEs = IO ThreadId
myThreadId IO ThreadId -> (ThreadId -> IO (Env es)) -> IO (Env es)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ThreadId
tid | ThreadId
tid0 ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
== ThreadId
tid -> Env es -> IO (Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Env es
es0
ThreadId
tid -> do
let wkTid :: Word64
wkTid = ThreadId -> Word64
weakThreadId ThreadId
tid
MVar Word64 -> IO Word64
forall a. MVar a -> IO a
S.readMVar MVar Word64
mvWeakTid IO Word64 -> (Word64 -> IO (Env es)) -> IO (Env es)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Word64
0 -> MVar Word64 -> (Word64 -> IO (Word64, Env es)) -> IO (Env es)
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
S.modifyMVar MVar Word64
mvWeakTid ((Word64 -> IO (Word64, Env es)) -> IO (Env es))
-> (Word64 -> IO (Word64, Env es)) -> IO (Env es)
forall a b. (a -> b) -> a -> b
$ \case
Word64
0 -> (Word64, Env es) -> IO (Word64, Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Word64
wkTid, Env es
es)
Word64
_ -> Int -> IO (Word64, Env es)
forall a. HasCallStack => Int -> a
noCapacityError Int
1
Word64
v | Word64
v Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
wkTid -> Env es -> IO (Env es)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Env es
es
| Bool
otherwise -> Int -> IO (Env es)
forall a. HasCallStack => Int -> a
noCapacityError Int
1
(forall r. effEs r -> IO r) -> IO a
k ((forall r. effEs r -> IO r) -> IO a)
-> (forall r. effEs r -> IO r) -> IO a
forall a b. (a -> b) -> a -> b
$ \effEs r
action -> effEs r -> Env es -> IO r
forall a b. Coercible a b => a -> b
coerce effEs r
action (Env es -> IO r) -> IO (Env es) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es)
getEs
{-# INLINE persistentConcSingleUnlift #-}
persistentConcUnlifts
:: ( HasCallStack
, forall r. Coercible (effEs r) (Env es -> IO r)
, forall r. Coercible (effLocalEs r) (Env localEs -> IO r)
)
=> Env es
-> Env localEs
-> Bool
-> Int
-> ((forall r. effEs r -> IO r) -> (forall r. effLocalEs r -> IO r) -> IO a)
-> IO a
persistentConcUnlifts :: forall (effEs :: Type -> Type) (es :: [Effect])
(effLocalEs :: Type -> Type) (localEs :: [Effect]) a.
(HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r),
forall r. Coercible (effLocalEs r) (Env localEs -> IO r)) =>
Env es
-> Env localEs
-> Bool
-> Int
-> ((forall r. effEs r -> IO r)
-> (forall r. effLocalEs r -> IO r) -> IO a)
-> IO a
persistentConcUnlifts Env es
es0 Env localEs
les0 Bool
cleanUp Int
threads (forall r. effEs r -> IO r)
-> (forall r. effLocalEs r -> IO r) -> IO a
k = do
Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
unless (Int
threads Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
forall a. HasCallStack => String -> a
error (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid number of threads: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
threads
ThreadId
tid0 <- IO ThreadId
myThreadId
IORef Storage
storageTemplate <- HasCallStack => IORef Storage -> IO (IORef Storage)
IORef Storage -> IO (IORef Storage)
cloneStorage Env es
es0.storage
Env es
esTemplate <- Env es -> IORef Storage -> IO (Env es)
forall (es :: [Effect]). Env es -> IORef Storage -> IO (Env es)
replaceStorage Env es
es0 IORef Storage
storageTemplate
Env localEs
lesTemplate <- Env localEs -> IORef Storage -> IO (Env localEs)
forall (es :: [Effect]). Env es -> IORef Storage -> IO (Env es)
replaceStorage Env localEs
les0 IORef Storage
storageTemplate
MVar (ThreadEntries (Env es, Env localEs))
mvEntries <- ThreadEntries (Env es, Env localEs)
-> IO (MVar (ThreadEntries (Env es, Env localEs)))
forall a. a -> IO (MVar a)
S.newMVar (ThreadEntries (Env es, Env localEs)
-> IO (MVar (ThreadEntries (Env es, Env localEs))))
-> ThreadEntries (Env es, Env localEs)
-> IO (MVar (ThreadEntries (Env es, Env localEs)))
forall a b. (a -> b) -> a -> b
$ Int
-> Word64Map (Weak (Env es, Env localEs))
-> ThreadEntries (Env es, Env localEs)
forall a. Int -> Word64Map (Weak a) -> ThreadEntries a
ThreadEntries Int
threads Word64Map (Weak (Env es, Env localEs))
forall a. Word64Map a
M.empty
let getEsLes :: IO (Env es, Env localEs)
getEsLes = IO ThreadId
myThreadId IO ThreadId
-> (ThreadId -> IO (Env es, Env localEs))
-> IO (Env es, Env localEs)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ThreadId
tid | ThreadId
tid0 ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
== ThreadId
tid -> (Env es, Env localEs) -> IO (Env es, Env localEs)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Env es
es0, Env localEs
les0)
ThreadId
tid -> do
ThreadEntries (Env es, Env localEs)
te0 <- MVar (ThreadEntries (Env es, Env localEs))
-> IO (ThreadEntries (Env es, Env localEs))
forall a. MVar a -> IO a
S.readMVar MVar (ThreadEntries (Env es, Env localEs))
mvEntries
let wkTid :: Word64
wkTid = ThreadId -> Word64
weakThreadId ThreadId
tid
case Word64
wkTid Word64
-> Word64Map (Weak (Env es, Env localEs))
-> Maybe (Weak (Env es, Env localEs))
forall a. Word64 -> Word64Map a -> Maybe a
`M.lookup` ThreadEntries (Env es, Env localEs)
te0.entries of
Just Weak (Env es, Env localEs)
wkEsLes -> Weak (Env es, Env localEs) -> IO (Env es, Env localEs)
forall a. HasCallStack => Weak a -> IO a
getWkTidEnv Weak (Env es, Env localEs)
wkEsLes
Maybe (Weak (Env es, Env localEs))
Nothing -> MVar (ThreadEntries (Env es, Env localEs))
-> (ThreadEntries (Env es, Env localEs)
-> IO (ThreadEntries (Env es, Env localEs), (Env es, Env localEs)))
-> IO (Env es, Env localEs)
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
S.modifyMVar MVar (ThreadEntries (Env es, Env localEs))
mvEntries ((ThreadEntries (Env es, Env localEs)
-> IO (ThreadEntries (Env es, Env localEs), (Env es, Env localEs)))
-> IO (Env es, Env localEs))
-> (ThreadEntries (Env es, Env localEs)
-> IO (ThreadEntries (Env es, Env localEs), (Env es, Env localEs)))
-> IO (Env es, Env localEs)
forall a b. (a -> b) -> a -> b
$ \ThreadEntries (Env es, Env localEs)
te -> case ThreadEntries (Env es, Env localEs)
te.capacity of
Int
0 -> Int
-> IO (ThreadEntries (Env es, Env localEs), (Env es, Env localEs))
forall a. HasCallStack => Int -> a
noCapacityError Int
threads
Int
1 -> do
Weak (Env es, Env localEs)
wkTidEsLes <- ThreadId
-> Word64
-> (Env es, Env localEs)
-> MVar (ThreadEntries (Env es, Env localEs))
-> Bool
-> IO (Weak (Env es, Env localEs))
forall a.
ThreadId
-> Word64 -> a -> MVar (ThreadEntries a) -> Bool -> IO (Weak a)
mkWeakThreadIdEnv ThreadId
tid Word64
wkTid (Env es
esTemplate, Env localEs
lesTemplate) MVar (ThreadEntries (Env es, Env localEs))
mvEntries Bool
cleanUp
let newEntries :: ThreadEntries (Env es, Env localEs)
newEntries = ThreadEntries
{ $sel:capacity:ThreadEntries :: Int
capacity = ThreadEntries (Env es, Env localEs)
te.capacity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
, $sel:entries:ThreadEntries :: Word64Map (Weak (Env es, Env localEs))
entries = Word64
-> Weak (Env es, Env localEs)
-> Word64Map (Weak (Env es, Env localEs))
-> Word64Map (Weak (Env es, Env localEs))
forall a. Word64 -> a -> Word64Map a -> Word64Map a
M.insert Word64
wkTid Weak (Env es, Env localEs)
wkTidEsLes ThreadEntries (Env es, Env localEs)
te.entries
}
(ThreadEntries (Env es, Env localEs), (Env es, Env localEs))
-> IO (ThreadEntries (Env es, Env localEs), (Env es, Env localEs))
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (ThreadEntries (Env es, Env localEs)
newEntries, (Env es
esTemplate, Env localEs
lesTemplate))
Int
_ -> do
IORef Storage
storage <- HasCallStack => IORef Storage -> IO (IORef Storage)
IORef Storage -> IO (IORef Storage)
cloneStorage IORef Storage
storageTemplate
Env es
es <- Env es -> IORef Storage -> IO (Env es)
forall (es :: [Effect]). Env es -> IORef Storage -> IO (Env es)
replaceStorage Env es
esTemplate IORef Storage
storage
Env localEs
les <- Env localEs -> IORef Storage -> IO (Env localEs)
forall (es :: [Effect]). Env es -> IORef Storage -> IO (Env es)
replaceStorage Env localEs
lesTemplate IORef Storage
storage
Weak (Env es, Env localEs)
wkTidEsLes <- ThreadId
-> Word64
-> (Env es, Env localEs)
-> MVar (ThreadEntries (Env es, Env localEs))
-> Bool
-> IO (Weak (Env es, Env localEs))
forall a.
ThreadId
-> Word64 -> a -> MVar (ThreadEntries a) -> Bool -> IO (Weak a)
mkWeakThreadIdEnv ThreadId
tid Word64
wkTid (Env es
es, Env localEs
les) MVar (ThreadEntries (Env es, Env localEs))
mvEntries Bool
cleanUp
let newEntries :: ThreadEntries (Env es, Env localEs)
newEntries = ThreadEntries
{ $sel:capacity:ThreadEntries :: Int
capacity = ThreadEntries (Env es, Env localEs)
te.capacity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
, $sel:entries:ThreadEntries :: Word64Map (Weak (Env es, Env localEs))
entries = Word64
-> Weak (Env es, Env localEs)
-> Word64Map (Weak (Env es, Env localEs))
-> Word64Map (Weak (Env es, Env localEs))
forall a. Word64 -> a -> Word64Map a -> Word64Map a
M.insert Word64
wkTid Weak (Env es, Env localEs)
wkTidEsLes ThreadEntries (Env es, Env localEs)
te.entries
}
(ThreadEntries (Env es, Env localEs), (Env es, Env localEs))
-> IO (ThreadEntries (Env es, Env localEs), (Env es, Env localEs))
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (ThreadEntries (Env es, Env localEs)
newEntries, (Env es
es, Env localEs
les))
(forall r. effEs r -> IO r)
-> (forall r. effLocalEs r -> IO r) -> IO a
k (\effEs r
action -> effEs r -> Env es -> IO r
forall a b. Coercible a b => a -> b
coerce effEs r
action (Env es -> IO r)
-> ((Env es, Env localEs) -> Env es)
-> (Env es, Env localEs)
-> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Env es, Env localEs) -> Env es
forall a b. (a, b) -> a
fst ((Env es, Env localEs) -> IO r) -> IO (Env es, Env localEs) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es, Env localEs)
getEsLes)
(\effLocalEs r
action -> effLocalEs r -> Env localEs -> IO r
forall a b. Coercible a b => a -> b
coerce effLocalEs r
action (Env localEs -> IO r)
-> ((Env es, Env localEs) -> Env localEs)
-> (Env es, Env localEs)
-> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Env es, Env localEs) -> Env localEs
forall a b. (a, b) -> b
snd ((Env es, Env localEs) -> IO r) -> IO (Env es, Env localEs) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es, Env localEs)
getEsLes)
{-# INLINE persistentConcUnlifts #-}
persistentConcSingleUnlifts
:: ( HasCallStack
, forall r. Coercible (effEs r) (Env es -> IO r)
, forall r. Coercible (effLocalEs r) (Env localEs -> IO r)
)
=> Env es
-> Env localEs
-> ((forall r. effEs r -> IO r) -> (forall r. effLocalEs r -> IO r) -> IO a)
-> IO a
persistentConcSingleUnlifts :: forall (effEs :: Type -> Type) (es :: [Effect])
(effLocalEs :: Type -> Type) (localEs :: [Effect]) a.
(HasCallStack, forall r. Coercible (effEs r) (Env es -> IO r),
forall r. Coercible (effLocalEs r) (Env localEs -> IO r)) =>
Env es
-> Env localEs
-> ((forall r. effEs r -> IO r)
-> (forall r. effLocalEs r -> IO r) -> IO a)
-> IO a
persistentConcSingleUnlifts Env es
es0 Env localEs
les0 (forall r. effEs r -> IO r)
-> (forall r. effLocalEs r -> IO r) -> IO a
k = do
ThreadId
tid0 <- IO ThreadId
myThreadId
IORef Storage
storage <- HasCallStack => IORef Storage -> IO (IORef Storage)
IORef Storage -> IO (IORef Storage)
cloneStorage Env es
es0.storage
Env es
es <- Env es -> IORef Storage -> IO (Env es)
forall (es :: [Effect]). Env es -> IORef Storage -> IO (Env es)
replaceStorage Env es
es0 IORef Storage
storage
Env localEs
les <- Env localEs -> IORef Storage -> IO (Env localEs)
forall (es :: [Effect]). Env es -> IORef Storage -> IO (Env es)
replaceStorage Env localEs
les0 IORef Storage
storage
MVar Word64
mvWeakTid <- Word64 -> IO (MVar Word64)
forall a. a -> IO (MVar a)
S.newMVar Word64
0
let getEsLes :: IO (Env es, Env localEs)
getEsLes = IO ThreadId
myThreadId IO ThreadId
-> (ThreadId -> IO (Env es, Env localEs))
-> IO (Env es, Env localEs)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ThreadId
tid | ThreadId
tid0 ThreadId -> ThreadId -> Bool
forall a. Eq a => a -> a -> Bool
== ThreadId
tid -> (Env es, Env localEs) -> IO (Env es, Env localEs)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Env es
es0, Env localEs
les0)
ThreadId
tid -> do
let wkTid :: Word64
wkTid = ThreadId -> Word64
weakThreadId ThreadId
tid
MVar Word64 -> IO Word64
forall a. MVar a -> IO a
S.readMVar MVar Word64
mvWeakTid IO Word64
-> (Word64 -> IO (Env es, Env localEs)) -> IO (Env es, Env localEs)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Word64
0 -> MVar Word64
-> (Word64 -> IO (Word64, (Env es, Env localEs)))
-> IO (Env es, Env localEs)
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
S.modifyMVar MVar Word64
mvWeakTid ((Word64 -> IO (Word64, (Env es, Env localEs)))
-> IO (Env es, Env localEs))
-> (Word64 -> IO (Word64, (Env es, Env localEs)))
-> IO (Env es, Env localEs)
forall a b. (a -> b) -> a -> b
$ \case
Word64
0 -> (Word64, (Env es, Env localEs))
-> IO (Word64, (Env es, Env localEs))
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Word64
wkTid, (Env es
es, Env localEs
les))
Word64
_ -> Int -> IO (Word64, (Env es, Env localEs))
forall a. HasCallStack => Int -> a
noCapacityError Int
1
Word64
v | Word64
v Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
wkTid -> (Env es, Env localEs) -> IO (Env es, Env localEs)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Env es
es, Env localEs
les)
| Bool
otherwise -> Int -> IO (Env es, Env localEs)
forall a. HasCallStack => Int -> a
noCapacityError Int
1
(forall r. effEs r -> IO r)
-> (forall r. effLocalEs r -> IO r) -> IO a
k (\effEs r
action -> effEs r -> Env es -> IO r
forall a b. Coercible a b => a -> b
coerce effEs r
action (Env es -> IO r)
-> ((Env es, Env localEs) -> Env es)
-> (Env es, Env localEs)
-> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Env es, Env localEs) -> Env es
forall a b. (a, b) -> a
fst ((Env es, Env localEs) -> IO r) -> IO (Env es, Env localEs) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es, Env localEs)
getEsLes)
(\effLocalEs r
action -> effLocalEs r -> Env localEs -> IO r
forall a b. Coercible a b => a -> b
coerce effLocalEs r
action (Env localEs -> IO r)
-> ((Env es, Env localEs) -> Env localEs)
-> (Env es, Env localEs)
-> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Env es, Env localEs) -> Env localEs
forall a b. (a, b) -> b
snd ((Env es, Env localEs) -> IO r) -> IO (Env es, Env localEs) -> IO r
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Env es, Env localEs)
getEsLes)
{-# INLINE persistentConcSingleUnlifts #-}
noCapacityError :: HasCallStack => Int -> a
noCapacityError :: forall a. HasCallStack => Int -> a
noCapacityError Int
threads = String -> a
forall a. HasCallStack => String -> a
error
(String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Number of other threads (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
threads String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") permitted to "
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"use the unlifting function was exceeded. Please increase the "
String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"limit or use the unlimited variant."
getWkTidEnv :: HasCallStack => Weak a -> IO a
getWkTidEnv :: forall a. HasCallStack => Weak a -> IO a
getWkTidEnv Weak a
wkTidEnv = Weak a -> IO (Maybe a)
forall v. Weak v -> IO (Maybe v)
deRefWeak Weak a
wkTidEnv IO (Maybe a) -> (Maybe a -> IO a) -> IO a
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe a
Nothing -> String -> IO a
forall a. HasCallStack => String -> a
error String
"Impossible, thread alive but its weak ref dead"
Just a
env -> a -> IO a
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
env
data ThreadEntries a = ThreadEntries
{ forall a. ThreadEntries a -> Int
capacity :: !Int
, forall a. ThreadEntries a -> Word64Map (Weak a)
entries :: !(M.Word64Map (Weak a))
}
mkWeakThreadIdEnv
:: ThreadId
-> Word64
-> a
-> S.MVar (ThreadEntries a)
-> Bool
-> IO (Weak a)
mkWeakThreadIdEnv :: forall a.
ThreadId
-> Word64 -> a -> MVar (ThreadEntries a) -> Bool -> IO (Weak a)
mkWeakThreadIdEnv (ThreadId ThreadId#
t#) Word64
wkTid a
es MVar (ThreadEntries a)
v = \case
Bool
True -> (State# RealWorld -> (# State# RealWorld, Weak a #)) -> IO (Weak a)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Weak a #))
-> IO (Weak a))
-> (State# RealWorld -> (# State# RealWorld, Weak a #))
-> IO (Weak a)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s0 ->
case ThreadId#
-> a
-> (State# RealWorld -> (# State# RealWorld, () #))
-> State# RealWorld
-> (# State# RealWorld, Weak# a #)
forall a b c.
a
-> b
-> (State# RealWorld -> (# State# RealWorld, c #))
-> State# RealWorld
-> (# State# RealWorld, Weak# b #)
mkWeak# ThreadId#
t# a
es State# RealWorld -> (# State# RealWorld, () #)
finalizer State# RealWorld
s0 of
(# State# RealWorld
s1, Weak# a
w #) -> (# State# RealWorld
s1, Weak# a -> Weak a
forall v. Weak# v -> Weak v
Weak Weak# a
w #)
Bool
False -> (State# RealWorld -> (# State# RealWorld, Weak a #)) -> IO (Weak a)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Weak a #))
-> IO (Weak a))
-> (State# RealWorld -> (# State# RealWorld, Weak a #))
-> IO (Weak a)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s0 ->
case ThreadId#
-> a -> State# RealWorld -> (# State# RealWorld, Weak# a #)
forall a b.
a -> b -> State# RealWorld -> (# State# RealWorld, Weak# b #)
mkWeakNoFinalizer# ThreadId#
t# a
es State# RealWorld
s0 of
(# State# RealWorld
s1, Weak# a
w #) -> (# State# RealWorld
s1, Weak# a -> Weak a
forall v. Weak# v -> Weak v
Weak Weak# a
w #)
where
IO State# RealWorld -> (# State# RealWorld, () #)
finalizer = MVar (ThreadEntries a)
-> (ThreadEntries a -> IO (ThreadEntries a)) -> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
S.modifyMVar_ MVar (ThreadEntries a)
v ((ThreadEntries a -> IO (ThreadEntries a)) -> IO ())
-> (ThreadEntries a -> IO (ThreadEntries a)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ThreadEntries a
te -> do
ThreadEntries a -> IO (ThreadEntries a)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (ThreadEntries a -> IO (ThreadEntries a))
-> ThreadEntries a -> IO (ThreadEntries a)
forall a b. (a -> b) -> a -> b
$ case (Word64 -> Weak a -> Maybe (Weak a))
-> Word64
-> Word64Map (Weak a)
-> (Maybe (Weak a), Word64Map (Weak a))
forall a.
(Word64 -> a -> Maybe a)
-> Word64 -> Word64Map a -> (Maybe a, Word64Map a)
M.updateLookupWithKey (\Word64
_ Weak a
_ -> Maybe (Weak a)
forall a. Maybe a
Nothing) Word64
wkTid ThreadEntries a
te.entries of
(Maybe (Weak a)
Nothing, Word64Map (Weak a)
_) -> ThreadEntries a
te
(Just Weak a
_, Word64Map (Weak a)
newEntries) -> ThreadEntries
{ $sel:capacity:ThreadEntries :: Int
capacity = case ThreadEntries a
te.capacity of
Int
0 -> Int
0
Int
n -> Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
, $sel:entries:ThreadEntries :: Word64Map (Weak a)
entries = Word64Map (Weak a)
newEntries
}