drama 0.1.0.2 → 0.1.0.3
raw patch · 6 files changed
+148/−128 lines, 6 filesnew-component:exe:example-shared-resourcenew-component:exe:example-workersPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +13/−2
- drama.cabal +21/−12
- examples/SharedResource.hs +0/−64
- examples/Workers.hs +0/−50
- examples/shared-resource.hs +64/−0
- examples/workers.hs +50/−0
CHANGELOG.md view
@@ -7,6 +7,16 @@ ## [Unreleased] +## [0.1.0.3] - 2021-02-20++### Added++- Examples now have their own executable components, separate from the library++### Removed++- Removed `SharedResource` and `Workers` modules from library+ ## [0.1.0.2] - 2021-02-20 ### Added@@ -36,8 +46,9 @@ Initial release -[Unreleased]: https://github.com/evanrelf/drama/compare/v0.1.0.2...HEAD-[0.1.0.1]: https://github.com/evanrelf/drama/releases/tag/v0.1.0.2+[Unreleased]: https://github.com/evanrelf/drama/compare/v0.1.0.3...HEAD+[0.1.0.3]: https://github.com/evanrelf/drama/releases/tag/v0.1.0.3+[0.1.0.2]: https://github.com/evanrelf/drama/releases/tag/v0.1.0.2 [0.1.0.1]: https://github.com/evanrelf/drama/releases/tag/v0.1.0.1 [0.1.0.0]: https://github.com/evanrelf/drama/releases/tag/v0.1.0.0
drama.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 name: drama-version: 0.1.0.2+version: 0.1.0.3 synopsis: Simple actor library for Haskell description: Simple actor library for Haskell category: Concurrency@@ -17,6 +17,7 @@ CHANGELOG.md LICENSE README.md+ examples/*.hs common common@@ -35,6 +36,13 @@ -fshow-warning-groups +common executable+ ghc-options:+ -threaded+ -rtsopts+ -with-rtsopts=-N++ common stan if impl(ghc >= 8.8) ghc-options:@@ -42,12 +50,6 @@ -hiedir=.hie -flag examples- description: Build examples- default: False- manual: True-- library import: common, stan hs-source-dirs: src@@ -58,11 +60,6 @@ exposed-modules: , Drama , Drama.Internal- if flag(examples)- hs-source-dirs: examples- exposed-modules:- , SharedResource- , Workers benchmark bench@@ -73,3 +70,15 @@ build-depends: , criterion ^>= 1.5.9.0 , drama+++executable example-shared-resource+ import: common, executable, stan+ main-is: examples/shared-resource.hs+ build-depends: drama+++executable example-workers+ import: common, executable, stan+ main-is: examples/workers.hs+ build-depends: drama
@@ -1,64 +0,0 @@-{-# LANGUAGE BlockArguments #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE NumericUnderscores #-}--module SharedResource (main) where--import Control.Concurrent (threadDelay)-import Control.Monad (forever)-import Control.Monad.IO.Class (MonadIO (..))-import Drama-import Prelude hiding (log)---main :: IO ()-main = run do- -- Spawn `logger` actor, which starts waiting for requests.- loggerAddress <- spawn logger-- -- Spawn two noisy actors, `fizzBuzz` and `navi`, which want to constantly- -- print to the console. Instead of running `putStrLn`, they will send- -- messages to `logger`.- _ <- spawn (fizzBuzz loggerAddress)- _ <- spawn (navi loggerAddress)-- -- Block `main` thread forever.- wait----- | Actor which encapsulates access to the console (a shared resource). By--- sending log messages to `logger`, instead of running `putStrLn` directly, we--- can avoid interleaving logs from actors running in parallel.-logger :: Actor String ()-logger = forever do- string <- receive- liftIO $ putStrLn string----- | Silly example actor which wants to print to the console-fizzBuzz :: Address String -> Actor () ()-fizzBuzz loggerAddress = do- let log = send loggerAddress-- loop (0 :: Int) \n -> do- if | n `mod` 15 == 0 -> log "FizzBuzz"- | n `mod` 3 == 0 -> log "Fizz"- | n `mod` 5 == 0 -> log "Buzz"- | otherwise -> log (show n)-- -- Delay included for nicer (slow) output- liftIO $ threadDelay 500_000-- continue (n + 1)----- | Silly example actor which wants to print to the console-navi :: Address String -> Actor () ()-navi loggerAddress = do- let log = send loggerAddress-- forever do- log "Hey, listen!"-- -- Delay included for nicer (slow) output- liftIO $ threadDelay 1_000_000
− examples/Workers.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE BlockArguments #-}--module Workers (main) where--import Control.Monad (replicateM, when)-import Control.Monad.IO.Class (MonadIO (..))-import Data.Function ((&))-import Drama---main :: IO ()-main = run do- -- Spawn `fib` actor, which starts waiting for requests.- fibAddress <- spawn fib-- -- Request fibonacci numbers from `fib`. `fib` will spawn three `fibWorker`s- -- to do all the work in the background, and then send `main` their results- -- once they finish.- myAddress <- here- [200, 400, 600] & mapM_ \n -> send fibAddress (myAddress, n)-- -- Receive results sent back from the `fibWorker`s, and print them to the- -- console.- replicateM 3 receive >>= mapM_ \(n, f) ->- liftIO $ putStrLn ("Fibonacci number " <> show n <> " is " <> show f)-- -- Tell `fib` to stop.- send fibAddress (myAddress, -1)-- -- Wait for `fib` to stop before exiting.- wait----- | Actor which immediately spawns and delegates to "worker" actors.-fib :: Actor (Address (Int, Integer), Int) ()-fib = do- (responseAddress, n) <- receive- when (n >= 0) do- _ <- spawn (fibWorker responseAddress n)- fib----- | "Worker" actor responsible for doing the real, time-consuming work.-fibWorker :: Address (Int, Integer) -> Int -> Actor () ()-fibWorker responseAddress n = send responseAddress (n, fibs !! n)----- | Infinite list of fibonacci numbers.-fibs :: [Integer]-fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
@@ -0,0 +1,64 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NumericUnderscores #-}++module Main (main) where++import Control.Concurrent (threadDelay)+import Control.Monad (forever)+import Control.Monad.IO.Class (MonadIO (..))+import Drama+import Prelude hiding (log)+++main :: IO ()+main = run do+ -- Spawn `logger` actor, which starts waiting for requests.+ loggerAddress <- spawn logger++ -- Spawn two noisy actors, `fizzBuzz` and `navi`, which want to constantly+ -- print to the console. Instead of running `putStrLn`, they will send+ -- messages to `logger`.+ _ <- spawn (fizzBuzz loggerAddress)+ _ <- spawn (navi loggerAddress)++ -- Block `main` thread forever.+ wait+++-- | Actor which encapsulates access to the console (a shared resource). By+-- sending log messages to `logger`, instead of running `putStrLn` directly, we+-- can avoid interleaving logs from actors running in parallel.+logger :: Actor String ()+logger = forever do+ string <- receive+ liftIO $ putStrLn string+++-- | Silly example actor which wants to print to the console+fizzBuzz :: Address String -> Actor () ()+fizzBuzz loggerAddress = do+ let log = send loggerAddress++ loop (0 :: Int) \n -> do+ if | n `mod` 15 == 0 -> log "FizzBuzz"+ | n `mod` 3 == 0 -> log "Fizz"+ | n `mod` 5 == 0 -> log "Buzz"+ | otherwise -> log (show n)++ -- Delay included for nicer (slow) output+ liftIO $ threadDelay 500_000++ continue (n + 1)+++-- | Silly example actor which wants to print to the console+navi :: Address String -> Actor () ()+navi loggerAddress = do+ let log = send loggerAddress++ forever do+ log "Hey, listen!"++ -- Delay included for nicer (slow) output+ liftIO $ threadDelay 1_000_000
+ examples/workers.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE BlockArguments #-}++module Main (main) where++import Control.Monad (replicateM, when)+import Control.Monad.IO.Class (MonadIO (..))+import Data.Function ((&))+import Drama+++main :: IO ()+main = run do+ -- Spawn `fib` actor, which starts waiting for requests.+ fibAddress <- spawn fib++ -- Request fibonacci numbers from `fib`. `fib` will spawn three `fibWorker`s+ -- to do all the work in the background, and then send `main` their results+ -- once they finish.+ myAddress <- here+ [200, 400, 600] & mapM_ \n -> send fibAddress (myAddress, n)++ -- Receive results sent back from the `fibWorker`s, and print them to the+ -- console.+ replicateM 3 receive >>= mapM_ \(n, f) ->+ liftIO $ putStrLn ("Fibonacci number " <> show n <> " is " <> show f)++ -- Tell `fib` to stop.+ send fibAddress (myAddress, -1)++ -- Wait for `fib` to stop before exiting.+ wait+++-- | Actor which immediately spawns and delegates to "worker" actors.+fib :: Actor (Address (Int, Integer), Int) ()+fib = do+ (responseAddress, n) <- receive+ when (n >= 0) do+ _ <- spawn (fibWorker responseAddress n)+ fib+++-- | "Worker" actor responsible for doing the real, time-consuming work.+fibWorker :: Address (Int, Integer) -> Int -> Actor () ()+fibWorker responseAddress n = send responseAddress (n, fibs !! n)+++-- | Infinite list of fibonacci numbers.+fibs :: [Integer]+fibs = 0 : 1 : zipWith (+) fibs (tail fibs)