Include async helpers

This commit is contained in:
Michael Snoyman 2014-03-07 07:34:00 +02:00
parent 065c1887ad
commit f1ca43e7c6
3 changed files with 54 additions and 4 deletions

View File

@ -11,11 +11,18 @@ module Yesod.WebSockets
, sourceWS , sourceWS
, sinkWSText , sinkWSText
, sinkWSBinary , sinkWSBinary
-- * Async helpers
, race
, race_
, concurrently
, concurrently_
) where ) where
import Control.Monad (when, forever) import qualified Control.Concurrent.Async as A
import Control.Monad (forever, void, when)
import Control.Monad.IO.Class (MonadIO (liftIO)) import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad.Trans.Control (control) import Control.Monad.Trans.Control (control)
import Control.Monad.Trans.Control (MonadBaseControl (liftBaseWith, restoreM))
import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT)) import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT))
import qualified Data.Conduit as C import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL import qualified Data.Conduit.List as CL
@ -83,3 +90,35 @@ sinkWSText = CL.mapM_ sendTextData
-- Since 0.1.0 -- Since 0.1.0
sinkWSBinary :: (MonadIO m, WS.WebSocketsData a) => C.Consumer a (WebSocketsT m) () sinkWSBinary :: (MonadIO m, WS.WebSocketsData a) => C.Consumer a (WebSocketsT m) ()
sinkWSBinary = CL.mapM_ sendBinaryData sinkWSBinary = CL.mapM_ sendBinaryData
-- | Generalized version of 'A.race'.
--
-- Since 0.1.0
race :: MonadBaseControl IO m => m a -> m b -> m (Either a b)
race x y = liftBaseWith (\run -> A.race (run x) (run y))
>>= either (fmap Left . restoreM) (fmap Right . restoreM)
-- | Generalized version of 'A.race_'.
--
-- Since 0.1.0
race_ :: MonadBaseControl IO m => m a -> m b -> m ()
race_ x y = void $ race x y
-- | Generalized version of 'A.concurrently'. Note that if your underlying
-- monad has some kind of mutable state, the state from the second action will
-- overwrite the state from the first.
--
-- Since 0.1.0
concurrently :: MonadBaseControl IO m => m a -> m b -> m (a, b)
concurrently x y = do
(resX, resY) <- liftBaseWith $ \run -> A.concurrently (run x) (run y)
x' <- restoreM resX
y' <- restoreM resY
return (x', y')
-- | Run two actions concurrently (like 'A.concurrently'), but discard their
-- results and any modified monadic state.
--
-- Since 0.1.0
concurrently_ :: MonadBaseControl IO m => m a -> m b -> m ()
concurrently_ x y = void $ liftBaseWith $ \run -> A.concurrently (run x) (run y)

View File

@ -3,6 +3,10 @@ import Yesod.Core
import Yesod.WebSockets import Yesod.WebSockets
import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy as TL
import Control.Monad (forever) import Control.Monad (forever)
import Control.Monad.Trans.Reader
import Control.Concurrent (threadDelay)
import Data.Time
import Conduit
data App = App data App = App
@ -12,11 +16,17 @@ mkYesod "App" [parseRoutes|
/ HomeR GET / HomeR GET
|] |]
timeSource :: MonadIO m => Source m TL.Text
timeSource = forever $ do
now <- liftIO getCurrentTime
yield $ TL.pack $ show now
liftIO $ threadDelay 5000000
getHomeR :: Handler Html getHomeR :: Handler Html
getHomeR = do getHomeR = do
webSockets $ forever $ do webSockets $ race_
msg <- receiveData (sourceWS $$ mapC TL.toUpper =$ sinkWSText)
sendTextData $ TL.toUpper msg (timeSource $$ sinkWSText)
defaultLayout $ defaultLayout $
toWidget toWidget
[julius| [julius|

View File

@ -23,6 +23,7 @@ library
, yesod-core >= 1.2.7 , yesod-core >= 1.2.7
, monad-control >= 0.3 , monad-control >= 0.3
, conduit >= 1.0.15.1 , conduit >= 1.0.15.1
, async >= 2.0.1.5
source-repository head source-repository head
type: git type: git