module Twee.Task(Task, newTask, checkTask) where
import System.CPUTime
import Data.IORef
import Control.Monad.IO.Class
data TaskData m a =
TaskData {
task_start :: !Integer,
task_last :: !Integer,
task_spent :: !Integer,
task_frequency :: !Double,
task_budget :: !Double,
task_what :: m a }
newtype Task m a = Task (IORef (TaskData m a))
newTask :: MonadIO m => Double -> Double -> m a -> m (Task m a)
newTask freq budget what = liftIO $ do
now <- getCPUTime
Task <$> newIORef (TaskData now now 0 freq budget what)
checkTask :: MonadIO m => Task m a -> m (Maybe a)
checkTask (Task ref) = do
task@TaskData{..} <- liftIO $ readIORef ref
now <- liftIO getCPUTime
if not (taskDue now task) then return Nothing else do
res <- task_what
after <- liftIO getCPUTime
liftIO $ writeIORef ref task {
task_last = after,
task_spent = task_spent + (afternow) }
return (Just res)
taskDue :: Integer -> TaskData m a -> Bool
taskDue now TaskData{..} =
fromInteger (now task_last) >= task_frequency * 10^12 &&
fromInteger (now task_start) * task_budget > fromInteger task_spent