module Data.Array.Accelerate.Array.Remote.Nursery (
Nursery(..), NRS, new, lookup, insert, cleanup, size
) where
import Data.Array.Accelerate.Error
import qualified Data.Array.Accelerate.Debug as D
import Prelude hiding ( lookup )
import Control.Concurrent.MVar
import Data.Int
import Data.IntMap ( IntMap )
import Data.Sequence ( Seq )
import Data.Word
import System.Mem.Weak ( Weak )
import qualified Data.IntMap.Strict as IM
import qualified Data.Sequence as Seq
import qualified Data.Traversable as Seq
data Nursery ptr = Nursery !(NRS ptr)
!(Weak (NRS ptr))
type NRS ptr = MVar (N ptr)
data N ptr = N !(IntMap (Seq (ptr Word8)))
!Int64
new :: (ptr Word8 -> IO ()) -> IO (Nursery ptr)
new delete = do
message "initialise nursery"
ref <- newMVar ( N IM.empty 0 )
weak <- mkWeakMVar ref (cleanup delete ref)
return $! Nursery ref weak
lookup :: Int -> Nursery ptr -> IO (Maybe (ptr Word8))
lookup !key (Nursery !ref !_) =
modifyMVar ref $ \nrs@( N im sz ) ->
let
(mv, nrs') = IM.updateLookupWithKey f key im
f _k v =
case Seq.viewl v of
Seq.EmptyL -> $internalError "lookup" "expected non-empty sequence"
_ Seq.:< vs -> if Seq.null vs then Nothing
else Just vs
in
case fmap Seq.viewl mv of
Just (v Seq.:< _) -> return ( N nrs' (sz fromIntegral key) , Just v )
_ -> return ( nrs, Nothing )
insert :: Int -> ptr Word8 -> Nursery ptr -> IO ()
insert !key !val (Nursery !ref _) =
let
f Nothing = Just (Seq.singleton val)
f (Just vs) = Just (vs Seq.|> val)
in
modifyMVar_ ref $ \(N im sz) ->
return $! N (IM.alter f key im) (sz + fromIntegral key)
cleanup :: (ptr Word8 -> IO ()) -> NRS ptr -> IO ()
cleanup delete !ref = do
message "nursery cleanup"
modifyMVar_ ref $ \(N nrs _) -> do mapM_ (Seq.mapM delete) (IM.elems nrs)
return ( N IM.empty 0 )
size :: Nursery ptr -> IO Int64
size (Nursery ref _) = withMVar ref $ \(N _ sz) -> return sz
message :: String -> IO ()
message msg = D.traceIO D.dump_gc ("gc: " ++ msg)