{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE Safe #-}
module System.Mem.Manager
(
selfishManager
, hardPageFaults
) where
import Control.Concurrent
import Control.Monad
import Data.IORef
import Foreign.C.Types
import System.Mem
foreign import ccall "getHardPageFaults" hardPageFaults :: IO CSize
selfishManager :: IO (ThreadId, IO Int)
selfishManager :: IO (ThreadId, IO Int)
selfishManager = do
IORef Int
collections <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
ThreadId
threadId <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ do
CSize
faults <- IO CSize
hardPageFaults
let go :: CSize -> IO b
go CSize
oldFaults = do
CSize
newFaults <- IO CSize
hardPageFaults
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CSize
newFaults CSize -> CSize -> Bool
forall a. Ord a => a -> a -> Bool
>= CSize
oldFaults CSize -> CSize -> CSize
forall a. Num a => a -> a -> a
+ CSize
10) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
IO ()
performMajorGC
IORef Int -> (Int -> Int) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Int
collections (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
Int -> IO ()
threadDelay Int
50000
CSize -> IO b
go CSize
newFaults
CSize -> IO ()
forall {b}. CSize -> IO b
go CSize
faults
(ThreadId, IO Int) -> IO (ThreadId, IO Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ThreadId
threadId, IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
collections)