packages feed

polysemy-conc 0.5.1.1 → 0.6.0.0

raw patch · 42 files changed

+433/−247 lines, 42 filesdep +incipit-coredep +polysemy-resumedep −data-defaultdep −reludedep −template-haskelldep ~polysemy-plugindep ~polysemy-timesetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: incipit-core, polysemy-resume

Dependencies removed: data-default, relude, template-haskell, text

Dependency ranges changed: polysemy-plugin, polysemy-time

API changes (from Hackage documentation)

+ Polysemy.Conc: interpretScopedResumable :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc: interpretScopedResumableH :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumable :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumableH :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc.Queue: readMaybe :: Member (Queue d) r => Sem r (Maybe d)

Files

+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
changelog.md view
@@ -1,5 +1,8 @@ # Unreleased +* Add `Resumable` support for `Scoped`.+* Add `Scoped` interpreters that allow the allocator to interpret additional effects used by the handler.+ # 0.5.0.0  * Add `mask` effects.
lib/Polysemy/Conc.hs view
@@ -104,6 +104,8 @@   interpretScoped,   interpretScopedH,   interpretScopedAs,+  interpretScopedResumable,+  interpretScopedResumableH,    -- * Monitoring   Monitor,@@ -175,7 +177,15 @@ import Polysemy.Conc.Interpreter.Queue.TB (interpretQueueTB) import Polysemy.Conc.Interpreter.Queue.TBM (interpretQueueTBM) import Polysemy.Conc.Interpreter.Race (interpretRace)-import Polysemy.Conc.Interpreter.Scoped (interpretScoped, interpretScopedAs, interpretScopedH, runScoped, runScopedAs)+import Polysemy.Conc.Interpreter.Scoped (+  interpretScoped,+  interpretScopedAs,+  interpretScopedH,+  interpretScopedResumable,+  interpretScopedResumableH,+  runScoped,+  runScopedAs,+  ) import Polysemy.Conc.Interpreter.Stack (ConcStack, runConc) import Polysemy.Conc.Interpreter.Sync (interpretScopedSync, interpretScopedSyncAs, interpretSync, interpretSyncAs) import Polysemy.Conc.Monitor (ClockSkewConfig (ClockSkewConfig), clockSkewConfig, monitorClockSkew)@@ -199,7 +209,7 @@  -- $mvar -- #mvar#--- An 'MVar' is abstracted as 'Sync' since it can be used to synchronize threads.+-- An 'Control.Concurrent.MVar' is abstracted as 'Sync' since it can be used to synchronize threads.  -- $race -- #race#
lib/Polysemy/Conc/Async.hs view
@@ -2,8 +2,6 @@ module Polysemy.Conc.Async where  import qualified Control.Concurrent.Async as Base-import Polysemy.Async (Async, async, cancel)-import Polysemy.Resource (Resource, bracket) import Polysemy.Time (MilliSeconds (MilliSeconds), TimeUnit)  import Polysemy.Conc.Effect.Race (Race)@@ -92,7 +90,7 @@       raise mb     f h (Sync.putBlock ()) --- |Variant of 'scheduleAsync' that directly interprets the 'MVar' used for signalling.+-- |Variant of 'scheduleAsync' that directly interprets the 'Control.Concurrent.MVar' used for signalling. scheduleAsyncIO ::   ∀ b r a .   Members [Resource, Async, Race, Embed IO] r =>
lib/Polysemy/Conc/AtomicState.hs view
@@ -1,7 +1,7 @@ -- |Description: AtomicState Interpreters module Polysemy.Conc.AtomicState where -import Polysemy.AtomicState (runAtomicStateTVar)+import Control.Concurrent.STM (newTVarIO)  -- |Convenience wrapper around 'runAtomicStateTVar' that creates a new 'TVar'. interpretAtomic ::@@ -10,6 +10,6 @@   a ->   InterpreterFor (AtomicState a) r interpretAtomic initial sem = do-  tv <- newTVarIO initial+  tv <- embed (newTVarIO initial)   runAtomicStateTVar tv sem {-# inline interpretAtomic #-}
lib/Polysemy/Conc/Data/QueueResult.hs view
@@ -17,7 +17,7 @@   |   -- |The queue was closed by the user.   Closed-  deriving (Eq, Show, Ord, Functor, Generic)+  deriving stock (Eq, Show, Ord, Functor, Generic)  instance Semigroup d => Semigroup (QueueResult d) where   Success d1 <> Success d2 = Success (d1 <> d2)
lib/Polysemy/Conc/Effect/Critical.hs view
@@ -1,6 +1,9 @@ {-# options_haddock prune #-}+ -- |Description: Critical effect module Polysemy.Conc.Effect.Critical where++import Prelude hiding (catch, run)  -- |An effect that catches exceptions. --
lib/Polysemy/Conc/Effect/Events.hs view
@@ -1,14 +1,14 @@ {-# options_haddock prune #-}+ -- |Description: Events/Consume Effects, Internal module Polysemy.Conc.Effect.Events where -import Polysemy (makeSem_) import Polysemy.Conc.Effect.Scoped (Scoped, scoped)  -- |Marker for the 'Scoped' resource for 'Events'. newtype EventResource resource =   EventResource { unEventToken :: resource }-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  -- |An event publisher that can be consumed from multiple threads. data Events (resource :: Type) (e :: Type) :: Effect where
lib/Polysemy/Conc/Effect/Mask.hs view
@@ -1,8 +1,7 @@ {-# options_haddock prune #-}+ -- |Description: Mask Effect, Internal module Polysemy.Conc.Effect.Mask where--import Polysemy (makeSem_)  import Polysemy.Conc.Effect.Scoped (Scoped, scoped) 
lib/Polysemy/Conc/Effect/Monitor.hs view
@@ -1,8 +1,9 @@ {-# options_haddock prune #-}+ -- |Description: Monitor Effect, Internal module Polysemy.Conc.Effect.Monitor where -import Polysemy (makeSem_)+import Control.Concurrent (MVar) import Polysemy.Time (NanoSeconds)  import Polysemy.Conc.Effect.Scoped (Scoped, scoped)@@ -10,7 +11,7 @@ -- |Marker type for the restarting action for 'Monitor'. data Restart =   Restart-  deriving (Eq, Show)+  deriving stock (Eq, Show)  -- |Mark a region as being subject to intervention by a monitoring program. -- This can mean that a thread is repeatedly checking a condition and cancelling this region when it is unmet.
lib/Polysemy/Conc/Effect/Race.hs view
@@ -1,8 +1,7 @@ {-# options_haddock prune #-}+ -- |Description: Race effect module Polysemy.Conc.Effect.Race where--import Polysemy (makeSem_)  import Polysemy.Time (TimeUnit) 
lib/Polysemy/Conc/Effect/Scoped.hs view
@@ -1,9 +1,7 @@ {-# options_haddock prune #-}+ -- |Description: Scoped Effect, Internal module Polysemy.Conc.Effect.Scoped where--import Polysemy (transform)-import Polysemy.Internal (send)  -- |@Scoped@ transforms a program so that @effect@ is associated with a @resource@ within that program. -- This requires the interpreter for @effect@ to be parameterized by @resource@ and constructed for every program using
lib/Polysemy/Conc/Effect/Sync.hs view
@@ -5,7 +5,7 @@ import Polysemy.Time (TimeUnit) import Polysemy.Conc.Effect.Scoped (Scoped) --- |Abstracts an 'MVar'.+-- |Abstracts an 'Control.Concurrent.MVar'. -- -- For documentation on the constructors, see the module "Polysemy.Conc.Effect.Sync". --
lib/Polysemy/Conc/Interpreter/Critical.hs view
@@ -2,8 +2,8 @@ module Polysemy.Conc.Interpreter.Critical where  import qualified Control.Exception as Exception-import Polysemy (runT) import Polysemy.Final (getInitialStateS, interpretFinal, runS)+import Prelude hiding (Catch)  import Polysemy.Conc.Effect.Critical (Critical (..)) @@ -16,9 +16,9 @@     Catch ma -> do       s <- getInitialStateS       o <- runS ma-      pure (run o s)+      pure (go o s)       where-        run ma' s =+        go ma' s =           Exception.catch (fmap Right <$> ma') \ se -> pure (Left se <$ s) {-# inline interpretCritical #-} 
lib/Polysemy/Conc/Interpreter/Events.hs view
@@ -1,11 +1,9 @@ {-# options_haddock prune #-}+ -- |Description: Events/Consume Interpreters, Internal module Polysemy.Conc.Interpreter.Events where  import Control.Concurrent.Chan.Unagi.Bounded (InChan, OutChan, dupChan, newChan, readChan, tryWriteChan)-import Polysemy (InterpretersFor)-import Polysemy.Async (Async)-import Polysemy.Resource (Resource)  import Polysemy.Conc.Async (withAsync_) import qualified Polysemy.Conc.Effect.Events as Events
lib/Polysemy/Conc/Interpreter/Interrupt.hs view
@@ -1,18 +1,25 @@ {-# options_haddock prune #-}+ -- |Description: Interrupt interpreters module Polysemy.Conc.Interpreter.Interrupt where +import Control.Concurrent (MVar, newEmptyMVar, readMVar, takeMVar, tryPutMVar, tryReadMVar) import qualified Control.Concurrent.Async as A import Control.Concurrent.Async (AsyncCancelled)+import Control.Concurrent.STM (TVar, newTVarIO) import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Data.Text.IO as Text-import Polysemy (getInspectorT, inspect, runT)-import Polysemy.Async (Async, async, await, cancel)-import Polysemy.AtomicState (runAtomicStateTVar) import Polysemy.Internal.Tactics (liftT) import Polysemy.Time (Seconds (Seconds))-import System.Posix.Signals (Handler (Catch, CatchInfo, CatchInfoOnce, CatchOnce), SignalInfo, installHandler, keyboardSignal)+import Prelude hiding (Catch)+import System.IO (stderr)+import System.Posix.Signals (+  Handler (Catch, CatchInfo, CatchInfoOnce, CatchOnce),+  SignalInfo,+  installHandler,+  keyboardSignal,+  )  import qualified Polysemy.Conc.Effect.Critical as Critical import Polysemy.Conc.Effect.Critical (Critical)@@ -51,7 +58,7 @@   Sem r () waitQuit = do   mv <- atomicGets quit-  readMVar mv+  embed (readMVar mv)  checkListeners ::   Members [AtomicState InterruptState, Embed IO] r =>@@ -59,7 +66,7 @@ checkListeners =   whenM (atomicGets (Set.null . listeners)) do     fin <- atomicGets finished-    void (tryPutMVar fin ())+    void (embed (tryPutMVar fin ()))  onQuit ::   Members [AtomicState InterruptState, Embed IO] r =>@@ -88,10 +95,10 @@   Sem r (SignalInfo -> Sem r ()) execInterrupt = do   InterruptState quitSignal finishSignal _ orig _ <- atomicGet-  whenM (tryPutMVar quitSignal ()) do+  whenM (embed (tryPutMVar quitSignal ())) do     traverse_ (uncurry processHandler) . Map.toList =<< atomicGets handlers     checkListeners-    takeMVar finishSignal+    embed (takeMVar finishSignal)   embed . orig <$ putErr "interrupt handlers finished"  registerHandler ::@@ -139,7 +146,7 @@         putErr "manual interrupt"         void execInterrupt     Interrupted ->-      liftT . fmap isJust . tryReadMVar =<< atomicGets quit+      liftT . fmap isJust . embed . tryReadMVar =<< atomicGets quit     KillOnQuit desc ma -> do       maT <- runT ma       ins <- getInspectorT@@ -172,7 +179,7 @@ originalHandler (CatchInfo thunk) =   thunk originalHandler _ =-  const pass+  const unit {-# inline originalHandler #-}  installSignalHandler ::@@ -193,9 +200,9 @@   ((SignalInfo -> IO ()) -> Handler) ->   InterpreterFor Interrupt r interpretInterruptWith consHandler sem = do-  quitMVar <- newEmptyMVar-  finishMVar <- newEmptyMVar-  state <- newTVarIO (InterruptState quitMVar finishMVar Set.empty (const pass) Map.empty)+  quitMVar <- embed newEmptyMVar+  finishMVar <- embed newEmptyMVar+  state <- embed (newTVarIO (InterruptState quitMVar finishMVar Set.empty (const unit) Map.empty))   orig <- embed $ installSignalHandler state consHandler   runAtomicStateTVar state do     atomicModify' \ s -> s {original = originalHandler orig}
lib/Polysemy/Conc/Interpreter/Mask.hs view
@@ -1,9 +1,9 @@ {-# options_haddock prune #-}+ -- |Description: Mask Interpreters, Internal module Polysemy.Conc.Interpreter.Mask where  import qualified Control.Exception as Base-import Polysemy (runTSimple) import Polysemy.Final (runS, withStrategicToFinal, withWeavingToFinal)  import Polysemy.Conc.Effect.Mask (
lib/Polysemy/Conc/Interpreter/Monitor.hs view
@@ -1,12 +1,10 @@ {-# options_haddock prune #-}+ -- |Description: Monitor Interpreters, Internal module Polysemy.Conc.Interpreter.Monitor where +import Control.Concurrent (MVar, newEmptyMVar, readMVar, tryTakeMVar) import qualified Control.Exception as Base-import Polysemy (embedFinal, runTSimple)-import Polysemy.Async (Async)-import Polysemy.Error (errorToIOFinal, fromExceptionSem)-import Polysemy.Resource (Resource) import qualified Polysemy.Time as Time import Polysemy.Time (Time) @@ -27,7 +25,8 @@  data MonitorCancel =   MonitorCancel-  deriving (Eq, Show, Exception)+  deriving stock (Eq, Show)+  deriving anyclass (Exception)  interpretMonitorCancel ::   Members [Race, Async, Final IO] r =>@@ -36,7 +35,7 @@ interpretMonitorCancel (MonitorResource CancelResource {..}) =   interpretH \case     Monitor ma ->-      leftM (Base.throw MonitorCancel) =<< Race.race (embedFinal @IO (readMVar signal)) (runTSimple ma)+      either (const (Base.throw MonitorCancel)) pure =<< Race.race (embedFinal @IO (readMVar signal)) (runTSimple ma)  monitorRestart ::   ∀ t d r a .@@ -44,14 +43,14 @@   MonitorCheck r ->   (MonitorResource CancelResource -> Sem r a) ->   Sem r a-monitorRestart (MonitorCheck interval check) run = do+monitorRestart (MonitorCheck interval check) use = do   sig <- embedFinal @IO newEmptyMVar   withAsync_ (Time.loop_ @t @d interval (check sig)) (spin sig)   where     spin sig = do       let res = (MonitorResource (CancelResource sig))       void (embedFinal @IO (tryTakeMVar sig))-      leftM (spin sig) =<< errorToIOFinal @MonitorCancel (fromExceptionSem @MonitorCancel (raise (run res)))+      either (const (spin sig)) pure =<< errorToIOFinal @MonitorCancel (fromExceptionSem @MonitorCancel (raise (use res)))  -- |Interpret @'Polysemy.Conc.Scoped' 'Monitor'@ with the 'Polysemy.Conc.Restart' strategy. -- This takes a check action that may put an 'MVar' when the scoped region should be restarted.
lib/Polysemy/Conc/Interpreter/Queue/Pure.hs view
@@ -1,14 +1,11 @@ -- |Description: Pure Queue Interpreters module Polysemy.Conc.Interpreter.Queue.Pure where -import Polysemy.AtomicState (atomicState')-import Polysemy.State (State, evalState, get, gets, put)- import Polysemy.Conc.AtomicState (interpretAtomic)-import qualified Polysemy.Conc.Effect.Queue as Queue-import Polysemy.Conc.Effect.Queue (Queue) import qualified Polysemy.Conc.Data.QueueResult as QueueResult import Polysemy.Conc.Data.QueueResult (QueueResult)+import qualified Polysemy.Conc.Effect.Queue as Queue+import Polysemy.Conc.Effect.Queue (Queue)  -- |Reinterpret 'Queue' as 'AtomicState' with a list that cannot be written to. -- Useful for testing.@@ -29,7 +26,7 @@     Queue.TryPeek ->       peek     Queue.Write _ ->-      pass+      unit     Queue.TryWrite _ ->       pure QueueResult.NotAvailable     Queue.WriteTimeout _ _ ->@@ -80,7 +77,7 @@     Queue.TryPeek ->       peek     Queue.Write _ ->-      pass+      unit     Queue.TryWrite _ ->       pure QueueResult.NotAvailable     Queue.WriteTimeout _ _ ->
lib/Polysemy/Conc/Interpreter/Queue/TB.hs view
@@ -3,6 +3,7 @@  import Control.Concurrent.STM (   TBQueue,+  atomically,   isFullTBQueue,   newTBQueueIO,   peekTBQueue,@@ -12,9 +13,9 @@   writeTBQueue,   ) +import qualified Polysemy.Conc.Data.QueueResult as QueueResult import qualified Polysemy.Conc.Effect.Queue as Queue import Polysemy.Conc.Effect.Queue (Queue)-import qualified Polysemy.Conc.Data.QueueResult as QueueResult import Polysemy.Conc.Effect.Race (Race) import Polysemy.Conc.Queue.Result (naResult) import Polysemy.Conc.Queue.Timeout (withTimeout)@@ -30,26 +31,26 @@ interpretQueueTBWith queue =   interpret \case     Queue.Read ->-      atomically (QueueResult.Success <$> readTBQueue queue)+      embed (atomically (QueueResult.Success <$> readTBQueue queue))     Queue.TryRead ->-      atomically (naResult <$> tryReadTBQueue queue)+      embed (atomically (naResult <$> tryReadTBQueue queue))     Queue.ReadTimeout timeout ->       withTimeout timeout (Just <$> readTBQueue queue)     Queue.Peek ->-      atomically (QueueResult.Success <$> peekTBQueue queue)+      embed (atomically (QueueResult.Success <$> peekTBQueue queue))     Queue.TryPeek ->-      atomically (naResult <$> tryPeekTBQueue queue)+      embed (atomically (naResult <$> tryPeekTBQueue queue))     Queue.Write d ->-      atomically (writeTBQueue queue d)+      embed (atomically (writeTBQueue queue d))     Queue.TryWrite d ->-      atomically do+      embed $ atomically do         ifM (isFullTBQueue queue) (pure QueueResult.NotAvailable) (QueueResult.Success <$> writeTBQueue queue d)     Queue.WriteTimeout timeout d ->       withTimeout timeout (Just <$> writeTBQueue queue d)     Queue.Closed ->       pure False     Queue.Close ->-      pass+      unit {-# inline interpretQueueTBWith #-}  -- |Interpret 'Queue' with a 'TBQueue'.
lib/Polysemy/Conc/Interpreter/Queue/TBM.hs view
@@ -1,7 +1,9 @@ {-# options_haddock prune #-}+ -- |Description: Queue Interpreters for 'TBMQueue' module Polysemy.Conc.Interpreter.Queue.TBM where +import Control.Concurrent.STM (atomically) import Control.Concurrent.STM.TBMQueue (   TBMQueue,   closeTBMQueue,@@ -14,7 +16,6 @@   tryWriteTBMQueue,   writeTBMQueue,   )-import Polysemy.Resource (Resource, bracket)  import qualified Polysemy.Conc.Effect.Queue as Queue import Polysemy.Conc.Effect.Queue (Queue)@@ -33,26 +34,26 @@ interpretQueueTBMWith queue =   interpret \case     Queue.Read ->-      atomically (closedResult <$> readTBMQueue queue)+      embed (atomically (closedResult <$> readTBMQueue queue))     Queue.TryRead ->-      atomically (closedNaResult <$> tryReadTBMQueue queue)+      embed (atomically (closedNaResult <$> tryReadTBMQueue queue))     Queue.ReadTimeout timeout ->       withTimeout timeout (readTBMQueue queue)     Queue.Peek ->-      atomically (closedResult <$> peekTBMQueue queue)+      embed (atomically (closedResult <$> peekTBMQueue queue))     Queue.TryPeek ->-      atomically (closedNaResult <$> tryPeekTBMQueue queue)+      embed (atomically (closedNaResult <$> tryPeekTBMQueue queue))     Queue.Write d ->-      atomically (writeTBMQueue queue d)+      embed (atomically (writeTBMQueue queue d))     Queue.TryWrite d ->-      atomically (closedBoolResult <$> tryWriteTBMQueue queue d)+      embed (atomically (closedBoolResult <$> tryWriteTBMQueue queue d))     Queue.WriteTimeout timeout d ->       withTimeout timeout do         ifM (isClosedTBMQueue queue) (pure Nothing) (Just <$> writeTBMQueue queue d)     Queue.Closed ->-      atomically (isClosedTBMQueue queue)+      embed (atomically (isClosedTBMQueue queue))     Queue.Close ->-      atomically (closeTBMQueue queue)+      embed (atomically (closeTBMQueue queue)) {-# inline interpretQueueTBMWith #-}  withTBMQueue ::@@ -62,7 +63,7 @@   (TBMQueue d -> Sem r a) ->   Sem r a withTBMQueue maxQueued =-  bracket (embed (newTBMQueueIO maxQueued)) (atomically . closeTBMQueue)+  bracket (embed (newTBMQueueIO maxQueued)) (embed . atomically . closeTBMQueue)  -- |Interpret 'Queue' with a 'TBMQueue'. interpretQueueTBM ::
lib/Polysemy/Conc/Interpreter/Scoped.hs view
@@ -1,13 +1,17 @@ {-# options_haddock prune #-}+ -- |Description: Scoped Interpreters, Internal module Polysemy.Conc.Interpreter.Scoped where  import Polysemy.Internal (Sem (Sem, runSem), liftSem)+import Polysemy.Internal.Index (InsertAtIndex)+import Polysemy.Internal.Tactics (liftT, runTactics) import Polysemy.Internal.Union (Weaving (Weaving), decomp, hoist, injWeaving)+import Polysemy.Resume (Stop, runStop, type (!!))+import Polysemy.Resume.Data.Resumable (Resumable (Resumable))+import Prelude hiding (run)  import Polysemy.Conc.Effect.Scoped (Scoped (InScope, Run))-import Polysemy (Tactical)-import Polysemy.Internal.Tactics (runTactics)  interpretH' ::   ∀ e r .@@ -76,17 +80,7 @@   (∀ r0 x . resource -> effect (Sem r0) x -> Sem r x) ->   InterpreterFor (Scoped resource effect) r interpretScoped withResource scopedHandler =-  run-  where-    run :: InterpreterFor (Scoped resource effect) r-    run =-      interpretH' \ (Weaving effect s wv ex _) -> case effect of-        Run resource act -> do-          x <- scopedHandler resource act-          pure (ex (x <$ s))-        InScope main ->-          ex <$> withResource \ resource -> run (wv (main resource <$ s))-+  interpretScopedH withResource \ r e -> liftT (scopedHandler r e)  -- |Variant of 'interpretScoped' in which the resource allocator is a plain action. interpretScopedAs ::@@ -96,3 +90,163 @@   InterpreterFor (Scoped resource effect) r interpretScopedAs resource =   interpretScoped \ f -> f =<< resource++-- |Combined higher-order interpreter for 'Scoped' and 'Resumable'.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it.+interpretScopedResumableH ::+  ∀ resource effect err r .+  (∀ x . (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) ->+  InterpreterFor (Scoped resource effect !! err) r+interpretScopedResumableH withResource scopedHandler =+  run+  where+    run :: InterpreterFor (Scoped resource effect !! err) r+    run =+      interpretH' \ (Weaving (Resumable inner) s' dist' ex' ins') ->+        case inner of+          Weaving effect s dist ex ins -> do+            let+              handleScoped = \case+                Run resource act ->+                  scopedHandler resource act+                InScope main ->+                  raise (withResource \ resource -> Compose <$> raise (run (dist' (dist (main resource <$ s) <$ s'))))+              tac =+                runTactics+                (Compose (s <$ s'))+                (raise . raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (ins <=< ins' . getCompose)+                (raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (handleScoped effect)+              exFinal = ex' . \case+                Right (Compose a) -> Right . ex <$> a+                Left err -> Left err <$ s'+            exFinal <$> runStop tac++-- |Combined interpreter for 'Scoped' and 'Resumable'.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it.+interpretScopedResumable ::+  ∀ resource effect err r .+  (∀ x . (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop err : r) x) ->+  InterpreterFor (Scoped resource effect !! err) r+interpretScopedResumable withResource scopedHandler =+  interpretScopedResumableH withResource \ r e -> liftT (scopedHandler r e)++interpretScopedWithH ::+  ∀ extra resource effect r r1 .+  r1 ~ (extra ++ r) =>+  InsertAtIndex 1 '[Scoped resource effect] r1 r (Scoped resource effect : r1) extra =>+  (∀ x . (resource -> Sem r1 x) -> Sem r x) ->+  (∀ m x . resource -> effect m x -> Tactical effect m r1 x) ->+  InterpreterFor (Scoped resource effect) r+interpretScopedWithH withResource scopedHandler =+  interpretH' \case+    Weaving (InScope main) s wv ex _ ->+      ex <$> withResource \ resource -> inScope (insertAt @1 @extra (wv (main resource <$ s)))+    _ ->+      error "top level Run"+  where+    inScope :: InterpreterFor (Scoped resource effect) r1+    inScope =+      interpretH' \case+        Weaving (Run resource act) s wv ex ins ->+          ex <$> runTactics s (raise . inScope . wv) ins (inScope . wv) (scopedHandler resource act)+        _ ->+          error "nested InScope"++interpretScopedWith ::+  ∀ extra resource effect r r1 .+  r1 ~ (extra ++ r) =>+  InsertAtIndex 1 '[Scoped resource effect] r1 r (Scoped resource effect : r1) extra =>+  (∀ x . (resource -> Sem r1 x) -> Sem r x) ->+  (∀ m x . resource -> effect m x -> Sem r1 x) ->+  InterpreterFor (Scoped resource effect) r+interpretScopedWith withResource scopedHandler =+  interpretScopedWithH @extra withResource \ r e -> liftT (scopedHandler r e)++interpretScopedWith_ ::+  ∀ extra effect r r1 .+  r1 ~ (extra ++ r) =>+  InsertAtIndex 1 '[Scoped () effect] r1 r (Scoped () effect : r1) extra =>+  (∀ x . Sem r1 x -> Sem r x) ->+  (∀ m x . effect m x -> Sem r1 x) ->+  InterpreterFor (Scoped () effect) r+interpretScopedWith_ withResource scopedHandler =+  interpretScopedWithH @extra (\ f -> withResource (f ())) \ () e -> liftT (scopedHandler e)++interpretScopedResumableWithH ::+  ∀ extra resource effect err r r1 .+  r1 ~ ((extra ++ '[Stop err]) ++ r) =>+  InsertAtIndex 1 '[Scoped resource effect !! err] r1 r (Scoped resource effect !! err : r1) (extra ++ '[Stop err]) =>+  (∀ x . (resource -> Sem r1 x) -> Sem (Stop err : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) ->+  InterpreterFor (Scoped resource effect !! err) r+interpretScopedResumableWithH withResource scopedHandler =+  run+  where+    run :: InterpreterFor (Scoped resource effect !! err) r+    run =+      interpretH' \ (Weaving (Resumable inner) s' dist' ex' ins') ->+        case inner of+          Weaving effect s dist ex ins -> do+            let+              handleScoped = \case+                Run _ _ ->+                  error "top level Run"+                InScope main ->+                  raise (withResource \ resource -> Compose <$> inScope (insertAt @1 @(extra ++ '[Stop err]) (dist' (dist (main resource <$ s) <$ s'))))+              tac =+                runTactics+                (Compose (s <$ s'))+                (raise . raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (ins <=< ins' . getCompose)+                (raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (handleScoped effect)+              exFinal = ex' . \case+                Right (Compose a) -> Right . ex <$> a+                Left err -> Left err <$ s'+            exFinal <$> runStop tac+    inScope :: InterpreterFor (Scoped resource effect !! err) r1+    inScope =+      interpretH' \ (Weaving (Resumable inner) s' dist' ex' ins') ->+        case inner of+          Weaving effect s dist ex ins -> do+            let+              handleScoped = \case+                Run resource act ->+                  scopedHandler resource act+                InScope _ ->+                  error "nested InScope"+              tac =+                runTactics+                (Compose (s <$ s'))+                (raise . inScope . fmap Compose . dist' . fmap dist . getCompose)+                (ins <=< ins' . getCompose)+                (inScope . fmap Compose . dist' . fmap dist . getCompose)+                (handleScoped effect)+              exFinal = ex' . \case+                Right (Compose a) -> Right . ex <$> a+                Left err -> Left err <$ s'+            exFinal <$> runStop (raise tac)++interpretScopedResumableWith ::+  ∀ extra resource effect err r r1 .+  r1 ~ ((extra ++ '[Stop err]) ++ r) =>+  InsertAtIndex 1 '[Scoped resource effect !! err] r1 r (Scoped resource effect !! err : r1) (extra ++ '[Stop err]) =>+  (∀ x . (resource -> Sem r1 x) -> Sem (Stop err : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem r1 x) ->+  InterpreterFor (Scoped resource effect !! err) r+interpretScopedResumableWith withResource scopedHandler =+  interpretScopedResumableWithH @extra withResource \ r e -> liftT (scopedHandler r e)++interpretScopedResumableWith_ ::+  ∀ extra effect err r r1 .+  r1 ~ ((extra ++ '[Stop err]) ++ r) =>+  InsertAtIndex 1 '[Scoped () effect !! err] r1 r (Scoped () effect !! err : r1) (extra ++ '[Stop err]) =>+  (∀ x . Sem r1 x -> Sem (Stop err : r) x) ->+  (∀ r0 x . effect (Sem r0) x -> Sem r1 x) ->+  InterpreterFor (Scoped () effect !! err) r+interpretScopedResumableWith_ withResource scopedHandler =+  interpretScopedResumableWith @extra (\ f -> withResource (f ())) (const scopedHandler)
lib/Polysemy/Conc/Interpreter/Stack.hs view
@@ -1,9 +1,7 @@ {-# options_haddock prune #-}+ -- |Description: Convenience Interpreters for all Conc Effects, Internal module Polysemy.Conc.Interpreter.Stack where--import Polysemy.Async (Async, asyncToIOFinal)-import Polysemy.Resource (Resource, resourceToIOFinal)  import Polysemy.Conc.Effect.Mask (Mask, UninterruptipleMask) import Polysemy.Conc.Effect.Race (Race)
lib/Polysemy/Conc/Interpreter/Sync.hs view
@@ -1,8 +1,18 @@ -- |Description: Sync Interpreters module Polysemy.Conc.Interpreter.Sync where -import Control.Concurrent (isEmptyMVar)-import Polysemy.Resource (Resource)+import Control.Concurrent (+  MVar,+  isEmptyMVar,+  newEmptyMVar,+  newMVar,+  putMVar,+  readMVar,+  takeMVar,+  tryPutMVar,+  tryReadMVar,+  tryTakeMVar,+  )  import Polysemy.Conc.Effect.Race (Race) import Polysemy.Conc.Effect.Scoped (Scoped)@@ -20,29 +30,29 @@ interpretSyncWith var =   interpret \case     Sync.Block ->-      readMVar var+      embed (readMVar var)     Sync.Wait interval ->-      rightToMaybe <$> Race.timeoutAs () interval (readMVar var)+      rightToMaybe <$> Race.timeoutAs () interval (embed (readMVar var))     Sync.Try ->-      tryReadMVar var+      embed (tryReadMVar var)     Sync.TakeBlock ->-      takeMVar var+      embed (takeMVar var)     Sync.TakeWait interval ->-      rightToMaybe <$> Race.timeoutAs () interval (takeMVar var)+      rightToMaybe <$> Race.timeoutAs () interval (embed (takeMVar var))     Sync.TakeTry ->-      tryTakeMVar var+      embed (tryTakeMVar var)     Sync.ReadBlock ->-      readMVar var+      embed (readMVar var)     Sync.ReadWait interval ->-      rightToMaybe <$> Race.timeoutAs () interval (readMVar var)+      rightToMaybe <$> Race.timeoutAs () interval (embed (readMVar var))     Sync.ReadTry ->-      tryReadMVar var+      embed (tryReadMVar var)     Sync.PutBlock d ->-      putMVar var d+      embed (putMVar var d)     Sync.PutWait interval d ->-      Race.timeoutAs_ False interval (True <$ putMVar var d)+      Race.timeoutAs_ False interval (True <$ embed (putMVar var d))     Sync.PutTry d ->-      tryPutMVar var d+      embed (tryPutMVar var d)     Sync.Empty ->       embed (isEmptyMVar var) @@ -52,7 +62,7 @@   Members [Race, Embed IO] r =>   InterpreterFor (Sync d) r interpretSync sem = do-  var <- newEmptyMVar+  var <- embed newEmptyMVar   interpretSyncWith var sem  -- |Interpret 'Sync' with an 'MVar' containing the specified value.@@ -62,7 +72,7 @@   d ->   InterpreterFor (Sync d) r interpretSyncAs d sem = do-  var <- newMVar d+  var <- embed (newMVar d)   interpretSyncWith var sem  -- |Interpret 'Sync' for locally scoped use with an empty 'MVar'.@@ -71,7 +81,7 @@   Members [Resource, Race, Embed IO] r =>   InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r interpretScopedSync =-  runScopedAs (SyncResources <$> newEmptyMVar) \ r -> interpretSyncWith (unSyncResources r)+  runScopedAs (SyncResources <$> embed newEmptyMVar) \ r -> interpretSyncWith (unSyncResources r)  -- |Interpret 'Sync' for locally scoped use with an 'MVar' containing the specified value. interpretScopedSyncAs ::@@ -80,4 +90,4 @@   d ->   InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r interpretScopedSyncAs d =-  runScopedAs (SyncResources <$> newMVar d) \ r -> interpretSyncWith (unSyncResources r)+  runScopedAs (SyncResources <$> embed (newMVar d)) \ r -> interpretSyncWith (unSyncResources r)
lib/Polysemy/Conc/Monitor.hs view
@@ -1,8 +1,9 @@ {-# options_haddock prune #-}+ -- |Description: Monitor Implementations, Internal module Polysemy.Conc.Monitor where -import Data.Default (Default (def))+import Control.Concurrent (tryPutMVar) import qualified Polysemy.Time as Time import Polysemy.Time (Minutes (Minutes), NanoSeconds, Seconds (Seconds), Time, TimeUnit, convert) import Torsor (Torsor, difference, minus)@@ -15,7 +16,7 @@     interval :: NanoSeconds,     tolerance :: NanoSeconds   }-  deriving (Eq, Show)+  deriving stock (Eq, Show)  -- |Smart constructor for 'ClockSkewConfig' that takes arbitrary 'TimeUnit's. clockSkewConfig ::
− lib/Polysemy/Conc/Prelude.hs
@@ -1,88 +0,0 @@-{-# options_haddock hide #-}-{-# language NoImplicitPrelude #-}--module Polysemy.Conc.Prelude (-  module Data.Kind,-  module Polysemy.Conc.Prelude,-  module GHC.Err,-  module Polysemy,-  module Polysemy.AtomicState,-  module Relude,-) where--import Control.Exception (try)-import Data.Kind (Type)-import GHC.Err (undefined)-import Polysemy (-  Effect,-  EffectRow,-  Embed,-  Final,-  InterpreterFor,-  Member,-  Members,-  Sem,-  WithTactics,-  embed,-  embedToFinal,-  interpret,-  interpretH,-  makeSem,-  pureT,-  raise,-  raiseUnder,-  raiseUnder2,-  raiseUnder3,-  reinterpret,-  runFinal,-  )-import Polysemy.AtomicState (AtomicState, atomicGet, atomicGets, atomicModify', atomicPut)-import Polysemy.Internal.Kind (Append)-import Relude hiding (-  Reader,-  State,-  Sum,-  Type,-  ask,-  asks,-  evalState,-  filterM,-  get,-  gets,-  hoistEither,-  modify,-  modify',-  put,-  readFile,-  runReader,-  runState,-  state,-  trace,-  traceShow,-  undefined,-  )--unify :: Either a a -> a-unify =-  either id id-{-# inline unify #-}--tryAny ::-  Member (Embed IO) r =>-  IO a ->-  Sem r (Either Text a)-tryAny =-  embed @IO . fmap (first show) . try @SomeException-{-# INLINE tryAny #-}--type a ++ b =-  Append a b--leftM ::-  Applicative m =>-  m b ->-  Either a b ->-  m b-leftM f =-  either (const f) pure-{-# inline leftM #-}
lib/Polysemy/Conc/Queue.hs view
@@ -20,6 +20,7 @@   write,   writeTimeout,   )+import Polysemy.Conc.Queue.Result (resultToMaybe)  -- |Read from a 'Queue' repeatedly until it is closed. --@@ -37,7 +38,7 @@       Queue.read >>= \case         QueueResult.Success d -> whenM (action d) spin         QueueResult.NotAvailable -> whenM na spin-        QueueResult.Closed -> pass+        QueueResult.Closed -> unit  -- |Read from a 'Queue' repeatedly until it is closed. --@@ -48,3 +49,11 @@   Sem r () loop action =   loopOr (pure True) \ d -> True <$ action d++-- |Read from a 'Queue' and convert the result to 'Maybe', returning 'Nothing' if there is no element available or the+-- queue has been closed.+readMaybe ::+  Member (Queue d) r =>+  Sem r (Maybe d)+readMaybe =+  resultToMaybe <$> read
lib/Polysemy/Conc/Queue/Timeout.hs view
@@ -1,6 +1,7 @@ -- |Description: Timeout Helper module Polysemy.Conc.Queue.Timeout where +import Control.Concurrent.STM (STM, atomically) import Polysemy.Time (TimeUnit)  import qualified Polysemy.Conc.Data.QueueResult as QueueResult@@ -19,4 +20,4 @@   Race.timeoutAs_ QueueResult.NotAvailable timeout reader'   where     reader' =-      maybe QueueResult.Closed QueueResult.Success <$> atomically readQ+      maybe QueueResult.Closed QueueResult.Success <$> embed (atomically readQ)
lib/Polysemy/Conc/Race.hs view
@@ -62,7 +62,7 @@   Sem r () ->   Sem r () timeoutU =-  timeout_ pass+  timeout_ unit {-# inline timeoutU #-}  -- |Variant of 'Race.timeout' that returns 'Maybe'.
lib/Polysemy/Conc/Sync.hs view
@@ -5,7 +5,6 @@   module Polysemy.Conc.Effect.Sync ) where -import Polysemy.Resource (Resource, finally) import qualified Polysemy.Time as Time import Polysemy.Time (Time, TimeUnit) 
− lib/Prelude.hs
@@ -1,5 +0,0 @@-module Prelude (-  module Polysemy.Conc.Prelude,-) where--import Polysemy.Conc.Prelude
polysemy-conc.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.34.6. -- -- see: https://github.com/sol/hpack  name:           polysemy-conc-version:        0.5.1.1+version:        0.6.0.0 synopsis:       Polysemy Effects for Concurrency description:    See <https://hackage.haskell.org/package/polysemy-conc/docs/Polysemy-Conc.html> category:       Concurrency@@ -54,18 +54,12 @@       Polysemy.Conc.Interpreter.Stack       Polysemy.Conc.Interpreter.Sync       Polysemy.Conc.Monitor-      Polysemy.Conc.Prelude       Polysemy.Conc.Queue       Polysemy.Conc.Queue.Result       Polysemy.Conc.Queue.Timeout       Polysemy.Conc.Race       Polysemy.Conc.Retry       Polysemy.Conc.Sync-  other-modules:-      Prelude-      Paths_polysemy_conc-  autogen-modules:-      Paths_polysemy_conc   hs-source-dirs:       lib   default-extensions:@@ -126,20 +120,17 @@       UndecidableInstances       UnicodeSyntax       ViewPatterns-  ghc-options: -flate-specialise -fspecialise-aggressively -Wall -Wredundant-constraints+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities   build-depends:       async     , base ==4.*     , containers-    , data-default >=0.2+    , incipit-core >=0.1.0.1     , polysemy >=1.6-    , polysemy-time >=0.1.4-    , relude >=0.7+    , polysemy-resume >=0.3+    , polysemy-time >=0.3     , stm     , stm-chans >=2-    , template-haskell-    , text-    , time     , torsor >=0.1     , unagi-chan >=0.4     , unix@@ -159,8 +150,8 @@       Polysemy.Conc.Test.MaskTest       Polysemy.Conc.Test.MonitorTest       Polysemy.Conc.Test.QueueTest+      Polysemy.Conc.Test.ScopedTest       Polysemy.Conc.Test.SyncTest-      Paths_polysemy_conc   hs-source-dirs:       test   default-extensions:@@ -221,13 +212,15 @@       UndecidableInstances       UnicodeSyntax       ViewPatterns-  ghc-options: -flate-specialise -fspecialise-aggressively -Wall -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -threaded -rtsopts -with-rtsopts=-N   build-depends:       async     , base ==4.*+    , incipit-core     , polysemy     , polysemy-conc-    , polysemy-plugin >=0.4+    , polysemy-plugin+    , polysemy-resume     , polysemy-test     , polysemy-time     , stm@@ -237,8 +230,6 @@     , unix   mixins:       base hiding (Prelude)-    , polysemy-conc hiding (Prelude)-    , polysemy-conc (Polysemy.Conc.Prelude as Prelude)   if impl(ghc >= 8.10)     ghc-options: -Wunused-packages   default-language: Haskell2010
readme.md view
@@ -1,8 +1,8 @@ # About -This library provides a few convenience [polysemy] effects for using STM queues, MVars, signal handling and racing.+This library provides [Polysemy] effects for using STM queues, MVars, signal handling and racing. -Please visit [hackage] for documentation.+Please visit [Hackage] for documentation. -[polysemy]: https://hackage.haskell.org/package/polysemy-[hackage]: https://hackage.haskell.org/package/polysemy-conc+[Polysemy]: https://hackage.haskell.org/package/polysemy+[Hackage]: https://hackage.haskell.org/package/polysemy-conc/docs/Polysemy-Conc.html
test/Main.hs view
@@ -12,6 +12,7 @@   test_queueTBM,   test_queueTimeoutTBM,   )+import Polysemy.Conc.Test.ScopedTest (test_scopedResumableWith, test_scopedWith) import Polysemy.Conc.Test.SyncTest (test_sync) import Polysemy.Test (unitTest) import Test.Tasty (TestTree, defaultMain, testGroup)@@ -42,6 +43,10 @@     testGroup "monitor" [       unitTest "basic" test_monitorBasic,       unitTest "clock skew" test_monitorClockSkew+    ],+    testGroup "scoped" [+      unitTest "scopedWith" test_scopedWith,+      unitTest "scopedResumableWith" test_scopedResumableWith     ]   ] 
test/Polysemy/Conc/Test/EventsTest.hs view
@@ -1,7 +1,6 @@ module Polysemy.Conc.Test.EventsTest where  import Control.Concurrent.Chan.Unagi.Bounded (OutChan)-import Polysemy.Async (async, asyncToIOFinal, await) import Polysemy.Test (UnitTest, assertJust, runTestAuto)  import qualified Polysemy.Conc.Effect.Events as Events
test/Polysemy/Conc/Test/InterruptTest.hs view
@@ -1,7 +1,7 @@ module Polysemy.Conc.Test.InterruptTest where -import Control.Concurrent.STM (modifyTVar)-import Polysemy.Async (asyncToIOFinal)+import Control.Concurrent (MVar, newEmptyMVar, putMVar, takeMVar)+import Control.Concurrent.STM (TVar, atomically, modifyTVar, newTVarIO, readTVarIO) import Polysemy.Test (UnitTest, assertEq, runTestAuto) import System.Posix (Handler (CatchInfoOnce), SignalInfo, installHandler, keyboardSignal, raiseSignal) @@ -18,8 +18,8 @@ test_interrupt :: UnitTest test_interrupt = do   runTestAuto do-    tv <- newTVarIO 0-    mv <- newEmptyMVar+    tv <- embed (newTVarIO 0)+    mv <- embed newEmptyMVar     embed (installHandler keyboardSignal (CatchInfoOnce (handler mv tv)) Nothing)     asyncToIOFinal $ interpretCritical $ interpretRace $ interpretInterrupt do       Interrupt.register "test 1" do@@ -27,6 +27,6 @@       Interrupt.register "test 2" do         atomically (modifyTVar tv (9 +))       embed (raiseSignal keyboardSignal)-    takeMVar mv-    result <- readTVarIO tv+    embed (takeMVar mv)+    result <- embed (readTVarIO tv)     assertEq @_ @IO 17 result
test/Polysemy/Conc/Test/LockTest.hs view
@@ -1,7 +1,6 @@ module Polysemy.Conc.Test.LockTest where  import Data.Time (Day, UTCTime)-import Polysemy.Async (asyncToIOFinal, sequenceConcurrently) import Polysemy.Test (UnitTest, assertEq, runTestAuto) import qualified Polysemy.Time as Time import Polysemy.Time (MicroSeconds (MicroSeconds), interpretTimeGhc)
test/Polysemy/Conc/Test/MaskTest.hs view
@@ -5,10 +5,10 @@ import qualified Control.Concurrent.Async as Base import Control.Concurrent.Async (asyncThreadId) import Control.Exception (throwTo)-import Polysemy (embedFinal)-import Polysemy.Async (Async, async, asyncToIOFinal, await)-import Polysemy.Error (fromExceptionSem, runError)+import GHC.Stack (withFrozenCallStack) import Polysemy.Test (Hedgehog, UnitTest, assertEq, evalLeft, runTestAuto)+import qualified Polysemy.Time as Time+import Polysemy.Time (MilliSeconds (MilliSeconds), interpretTimeGhc) import System.IO.Error (userError)  import Polysemy.Conc.AtomicState (interpretAtomic)@@ -17,8 +17,6 @@ import Polysemy.Conc.Interpreter.Mask (interpretUninterruptibleMaskFinal) import Polysemy.Conc.Interpreter.Race (interpretRace) import Polysemy.Conc.Interpreter.Sync (interpretSync)-import qualified Polysemy.Time as Time-import Polysemy.Time (interpretTimeGhc, MilliSeconds (MilliSeconds))  kill ::   Member (Final IO) r =>
test/Polysemy/Conc/Test/MonitorTest.hs view
@@ -2,8 +2,8 @@  module Polysemy.Conc.Test.MonitorTest where +import Control.Concurrent (MVar, putMVar) import Data.Time (UTCTime)-import Polysemy.Async (async, asyncToIOFinal, await) import Polysemy.Test (UnitTest, assertEq, assertJust, runTestAuto) import qualified Polysemy.Time as Time import Polysemy.Time (@@ -43,7 +43,7 @@   MVar () ->   Sem r () checker signal =-  Sync.takeBlock *> putMVar signal ()+  Sync.takeBlock *> embed (putMVar signal ())  test_monitorBasic :: UnitTest test_monitorBasic =
test/Polysemy/Conc/Test/QueueTest.hs view
@@ -1,9 +1,9 @@ module Polysemy.Conc.Test.QueueTest where -import Polysemy.Async (Async, asyncToIOFinal) import Polysemy.Test (UnitTest, assertEq, assertJust, runTestAuto) import Polysemy.Time (MilliSeconds (MilliSeconds), interpretTimeGhc) import Polysemy.Time.Ghc (GhcTime)+import Prelude hiding (run)  import qualified Polysemy.Conc.Data.QueueResult as QueueResult import Polysemy.Conc.Data.QueueResult (QueueResult)
+ test/Polysemy/Conc/Test/ScopedTest.hs view
@@ -0,0 +1,99 @@+{-# options_ghc -fplugin=Polysemy.Plugin #-}++module Polysemy.Conc.Test.ScopedTest where++import Control.Concurrent.STM (TVar, atomically, newTVarIO, readTVarIO, writeTVar)+import Polysemy.Resume (Stop, stop, (!!))+import Polysemy.Test (UnitTest, runTestAuto, (===))++import Polysemy.Conc.Effect.Scoped (scoped)+import Polysemy.Conc.Interpreter.Scoped (interpretScopedResumableWithH, interpretScopedWithH)++data E :: Effect where+  E1 :: E m Int+  E2 :: E m Int++makeSem ''E++data F :: Effect where+  F :: F m Int++makeSem ''F++handleE ::+  Member (Embed IO) r =>+  TVar Int ->+  E m a ->+  Tactical effect m (F : r) a+handleE tv = \case+  E1 -> do+    i1 <- embed (readTVarIO tv)+    i2 <- f+    pureT (i1 + i2 + 10)+  E2 ->+    pureT (-1)++interpretF ::+  Member (Embed IO) r =>+  TVar Int ->+  InterpreterFor F r+interpretF tv =+  interpret \ F -> do+    embed (atomically (writeTVar tv 7))+    pure 5++scope ::+  Member (Embed IO) r =>+  (TVar Int -> Sem (F : r) a) ->+  Sem r a+scope use = do+  tv <- embed (newTVarIO 20)+  interpretF tv (use tv)++test_scopedWith :: UnitTest+test_scopedWith =+  runTestAuto $ interpretScopedWithH @'[F] scope handleE do+    i1 <- scoped e1+    i2 <- scoped e1+    i1 === 35+    i2 === 35++handleRE ::+  Member (Embed IO) r =>+  TVar Int ->+  E m a ->+  Tactical effect m (F : Stop Int : r) a+handleRE tv = \case+  E1 -> do+    i1 <- embed (readTVarIO tv)+    i2 <- f+    _ <- stop (i1 + i2)+    pureT (i1 + i2 + 10)+  E2 ->+    pureT =<< f++interpretFR ::+  Members [Stop Int, Embed IO] r =>+  TVar Int ->+  InterpreterFor F r+interpretFR tv =+  interpret \ F -> do+    embed (atomically (writeTVar tv 7))+    pure 5++scopeR ::+  Member (Embed IO) r =>+  (TVar Int -> Sem (F : Stop Int : r) a) ->+  Sem (Stop Int : r) a+scopeR use = do+  tv <- embed (newTVarIO 20)+  _ <- interpretF tv (use tv)+  stop . (50 +) =<< embed (readTVarIO tv)++test_scopedResumableWith :: UnitTest+test_scopedResumableWith =+  runTestAuto $ interpretScopedResumableWithH @'[F] scopeR handleRE do+    i1 <- scoped e1 !! pure+    i2 <- scoped e2 !! pure+    i1 === 25+    i2 === 57
test/Polysemy/Conc/Test/SyncTest.hs view
@@ -1,7 +1,7 @@ module Polysemy.Conc.Test.SyncTest where -import Polysemy.Async (Async, asyncToIOFinal, sequenceConcurrently) import Polysemy.Test (UnitTest, assertEq, runTestAuto)+import Prelude hiding (run)  import Polysemy.Conc.Effect.Race (Race) import qualified Polysemy.Conc.Effect.Sync as Sync