chan 0.0.4 → 0.0.4.1
raw patch · 4 files changed
+31/−18 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +16/−9
- chan.cabal +2/−2
- src/Control/Concurrent/Chan/Extra.hs +1/−2
- test/Spec.hs +12/−5
README.md view
@@ -1,17 +1,21 @@+ # chan This is just some extra `Chan` and `TChan` kit that might help the average user. It relies on spawning threads with `async` and either canceling (debouncing) or waiting (throttling) messages. -Unfortunately, the current design is untyped in the sense that the channel which you supply is the+Unfortunately, the current design is slightly untyped in the sense that the channel which you supply is the _output_ channel, and the returned channel is the one you would write to. I'm not sure how this should-be fixed.+be fixed. There's a series of "typed" alternatives to each underlying channel type, that allows users to+restrict them to "read-only", "write-only", or "Writable a => ..." etc. An example might be the following: ```haskell import Control.Concurrent.Chan (readChan)-import Control.Concurrent.Chan.Extra (throttleStatic, intersperseStatic)+import Control.Concurrent.Chan.Scope (Scope (..))+import Control.Concurrent.Chan.Typed (ChanRW)+import Control.Concurrent.Chan.Extra (allowReading, throttleStatic, intersperseStatic) @@ -19,23 +23,26 @@ data SomeMessage = Ping+ | Foo -- | ... -throttleLayer :: Chan SomeMessage -> IO (Chan SomeMessage)+throttleLayer :: ChanRW 'Read SomeMessage -> IO (ChanRW 'Write SomeMessage) throttleLayer output = do (x,_) <- throttleStatic output 1000000 -- nanoseconds, = 1 second pure x -pingLayer :: Chan SomeMessage -> IO (Chan SomeMessage)+pingLayer :: ChanRW 'Read SomeMessage -> IO (ChanRW 'Write SomeMessage) pingLayer output = do (x,_,_) <- intersperseStatic output (pure Ping) 1000000 pure x -performWebsocket :: Chan SomeMessage -> IO ()+performWebsocket :: ChanRW 'Read SomeMessage -> IO () performWebsocket output = do- output' <- pingLayer =<< throttleLayer output- _ <- async $ forever $ do- msg <- readChan output'+ sendable <- pingLayer . allowReading =<< throttleLayer output+ emittingThread <- async $ forever $ do+ -- the thread that actually facilitates the sending of messages queued in the chans+ msg <- readChanRW output send msg -- something like that - it'll include Ping messages for us, -- and throttle the outgoing messages at the same time.+ writeChanRW sendable Foo ```
chan.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 9429247fea789bb683e6f4ed7fb173854b095d3e98824b896891eb68655e73a8+-- hash: ccb631c185767be2ee9b87d1fdc3c68a599868947989a396f06221b2c06a9b22 name: chan-version: 0.0.4+version: 0.0.4.1 synopsis: Some extra kit for Chans description: Please see the README on Github at <https://github.com/athanclark/chan#readme> category: Concurrency
src/Control/Concurrent/Chan/Extra.hs view
@@ -16,11 +16,10 @@ ( TChanRW (..), writeTChanRW, readTChanRW, newTChanRW) import Control.Concurrent.Chan.Scope (Scope (..), Writable, Readable) -import Data.IORef (newIORef, readIORef, writeIORef) import Control.Monad (forever) import Control.Concurrent (threadDelay) import Control.Concurrent.MVar (newEmptyMVar, tryTakeMVar, putMVar)-import Control.Concurrent.Chan (Chan, readChan, writeChan, newChan)+import Control.Concurrent.Chan (Chan) import Control.Concurrent.Async (Async, async, cancel, wait) import Control.Concurrent.STM (atomically, tryTakeTMVar, putTMVar, newEmptyTMVarIO)
test/Spec.hs view
@@ -1,15 +1,15 @@ import Control.Monad (forever) import Control.Concurrent (threadDelay) import Control.Concurrent.Chan (newChan, writeChan, readChan)-import Control.Concurrent.Chan.Extra (debounceStatic, throttleStatic, intersperseStatic)+import Control.Concurrent.Chan.Extra (ChanExtra (debounceStatic, throttleStatic, intersperseStatic)) import Control.Concurrent.Async (async) import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar) import Control.Concurrent.STM (atomically) import Control.Concurrent.STM.TChan (newTChan, writeTChan, readTChan)-import qualified Control.Concurrent.STM.TChan.Extra as TChan import Control.Concurrent.STM.TMVar (newEmptyTMVar, putTMVar, takeTMVar) +chanDebounceTest :: IO () chanDebounceTest = do putStrLn "Debounce ---------" outgoing <- newChan@@ -35,6 +35,7 @@ pure () +chanThrottleTest :: IO () chanThrottleTest = do putStrLn "Throttle ---------" outgoing <- newChan@@ -60,6 +61,7 @@ pure () +chanIntersperseTest :: IO () chanIntersperseTest = do putStrLn "Intersperse ---------" outgoing <- newChan@@ -84,15 +86,17 @@ pure () +chanTests :: IO () chanTests = do chanDebounceTest chanThrottleTest chanIntersperseTest +tchanDebounceTests :: IO () tchanDebounceTests = do putStrLn "Debounce STM ---------" outgoing <- atomically newTChan- (incoming, _) <- TChan.debounceStatic 1000000 outgoing+ (incoming, _) <- debounceStatic 1000000 outgoing lock <- atomically newEmptyTMVar @@ -114,10 +118,11 @@ pure () +tchanThrottleTests :: IO () tchanThrottleTests = do putStrLn "Throttle STM ---------" outgoing <- atomically newTChan- (incoming, _) <- TChan.throttleStatic 1000000 outgoing+ (incoming, _) <- throttleStatic 1000000 outgoing lock <- atomically newTChan @@ -140,10 +145,11 @@ pure () +tchanIntersperseTests :: IO () tchanIntersperseTests = do putStrLn "Intersperse STM ---------" outgoing <- atomically newTChan- (incoming, _, _) <- TChan.intersperseStatic 1000000 (pure 0) outgoing+ (incoming, _, _) <- intersperseStatic 1000000 (pure 0) outgoing lock <- atomically newEmptyTMVar @@ -164,6 +170,7 @@ pure () +tchanTests :: IO () tchanTests = do tchanDebounceTests tchanThrottleTests