-- | module Process ( Id, spawn, sleep, kill, ) where import Basics import qualified Control.Concurrent import qualified Control.Concurrent.Async as Async import Internal.Shortcut import qualified Platform.Internal as Internal import qualified Result import Task (Task) import qualified Prelude -- | A light-weight process that runs concurrently. You can use @spawn@ to get -- a bunch of different tasks running in different processes. The Elm Haskell -- will interleave their progress. So if a task is taking too long, we will -- pause it at an @andThen@ and switch over to other stuff. -- -- __Note:__ We make a distinction between concurrency which means interleaving -- different sequences and parallelism which means running different sequences -- at the exact same time. For example, a time-sharing system is definitely -- concurrent, but not necessarily parallel. newtype Id = Id (Async.Async ()) -- | Run a task in its own light-weight process. In the following example, -- @task1@ and @task2@ will be interleaved. If @task1@ makes a long HTTP -- request or is just taking a long time, we can hop over to @task2@ and do -- some work there. -- -- > spawn task1 -- > |> Task.andThen (\_ -> spawn task2) -- -- __Note:__ This creates a relatively restricted kind of Process because it -- cannot receive any messages. More flexibility for user-defined processes -- will come in a later release! spawn :: Task x a -> Task y Id spawn (Internal.Task f) = Internal.Task ( \handler -> f handler |> Async.async |> map (Result.Ok << Id << map (\_ -> ())) ) -- | Block progress on the current process for the given number of -- milliseconds. The JavaScript equivalent of this is @setTimeout@ which lets -- you delay work until later. sleep :: Float -> Task x () sleep delay = Internal.Task (\_ -> map Result.Ok (Control.Concurrent.threadDelay (Prelude.floor (delay * 1000)))) -- | Sometimes you @spawn@ a process, but later decide it would be a waste to -- have it keep running and doing stuff. The @kill@ function will force a -- process to bail on whatever task it is running. So if there is an HTTP -- request in flight, it will also abort the request. kill :: Id -> Task x () kill (Id async) = Internal.Task (\_ -> map Result.Ok (Async.cancel async))