packages feed

polysemy-conc-0.3.0.0: lib/Polysemy/Conc/Sync.hs

-- |Description: Sync Combinators
module Polysemy.Conc.Sync (
  module Polysemy.Conc.Sync,
  module Polysemy.Conc.Effect.Sync
) where

import qualified Polysemy.Time as Time
import Polysemy.Time (Time, TimeUnit)

import Polysemy.Conc.Effect.Scoped (Scoped, scoped)
import qualified Polysemy.Conc.Effect.Sync as Sync
import Polysemy.Conc.Effect.Sync (
  ScopedSync,
  Sync,
  SyncResources,
  block,
  empty,
  putBlock,
  putTry,
  putWait,
  readBlock,
  readTry,
  readWait,
  takeBlock,
  takeTry,
  takeWait,
  try,
  wait,
  )

-- |Run an action repeatedly until the 'Sync' variable is available.
whileEmpty ::
  ∀ a r .
  Member (Sync a) r =>
  Sem r () ->
  Sem r ()
whileEmpty action =
  spin
  where
    spin = do
      action
      whenM (not <$> Sync.empty @a) spin

-- |Run an action repeatedly until the 'Sync' variable is available, waiting for the specified time between executions.
whileEmptyInterval ::
  ∀ a u t d r .
  TimeUnit u =>
  Members [Time t d, Sync a] r =>
  u ->
  Sem r () ->
  Sem r ()
whileEmptyInterval interval action =
  spin
  where
    spin = do
      action
      whenM (not <$> Sync.empty @a) (Time.sleep @t @d interval *> spin)

-- |Run an action with a locally scoped 'Sync' variable.
withSync ::
  ∀ d res r .
  Member (Scoped (SyncResources res) (Sync d)) r =>
  InterpreterFor (Sync d) r
withSync =
  scoped @(SyncResources res)