{-# OPTIONS_GHC -Wno-unused-imports #-} -- | -- Module: Queries Tutorial -- Description: How To Mischief. -- -- [Previous Chapter: Keeping Track of Time]("Mischief.ECS.Tutorial.Guides.Time") -- -- [Next Chapter: Events and Messages]("Mischief.ECS.Tutorial.Guides.Events") -- -- [Main Page]("Mischief.ECS") module Mischief.ECS.Tutorial.Guides.Parallelism ( -- * Learn You an ECS for Great Mischief! - 2.9. Parallelism and Asynchronicity -- $intro -- * The System Monads -- $monad -- * Running Systems in Parallel -- $par -- * Iterating in Parallel -- $parFor -- * Querying in Parallel -- $qpar -- * Asynchronicity -- $async -- * [Next Chapter: Events and Messages]("Mischief.ECS.Tutorial.Guides.Events") ) where import Mischief.ECS -- $intro -- Mischief offers a few primitives for making systems run in parallel or asynchronously. -- $monad -- There is another monad that acts similary to @System@. It is called @ParSystem@, and -- it doesn't allow for immediate mutations of the World. -- -- Both @ParSystem@ and @System@ instance the @MonadSystem@ class, which you can use to write functions that work with both: -- -- @ -- f :: (MonadSystem w m) => m () -- @ -- -- Functions such as @query@, @query_@, @single@ work with both monads, since they only read data. -- -- Functions that mutate the world only work with @System@, requiring you to use @defer@ (see previous chapter) when used in @ParSystem@: -- -- @ -- 'defer' $ 'insert' (Health 100) bob -- @ -- $par -- You can run a list of @ParSystems@ in parallel using the @par@ function: -- -- @ -- par [foo, bar] -- @ -- $parFor -- You can iterate over Foldables in parallel using @parFor@: -- -- @ -- names <- 'query' ['q'|Entity, Name|] -- 'parFor' names $ \\(entity, Name name) -> do -- 'defer' $ 'insert' (Name $ name ++ \"2\") entity -- @ -- $qpar -- You can parallelize any @Query ParSystem a@ using @qpar@: -- -- @ -- names <- -- ['q'|Name / With Player|] -- & 'qpar' -- & 'query' -- @ -- $async -- Mischief has a couple of primitived that allow running systems asynchronously. -- -- === runAfter -- -- Asynchonicity in Mischief can be achieved using the @runAfter@ primtitive. -- You provide it an 'IO' action that returns an @a@, and a system which consumes that @a@. -- -- The 'IO' will be ran fully asychrnously and then will add the system to a special async-friendly deferred list that -- will be applied at the first available sync point. -- -- We can look at @delay@ as an example of how this may be useful: -- -- @ -- 'delay' d system = 'runAfter' ('threadDelay' d) ('const' system) -- @ -- -- Whcih allows delaying any system by an amount of time: -- -- @ -- 'delay' 0.5 $ 'insert' (Health 100) player -- @ -- -- === Repeaters -- -- Repeaters are another way of running async systems. -- -- A Repeater will run the given system at the given interval of time. This Repeater will -- print \"Hello!\" once per second: -- -- @ -- 'spawn_' 'Repeater' 1 ('info' \"Hello!\") -- @ -- -- Repeaters can be despawned to stop them from running.