From d94b4a1c2337f8717984166f2346b95371a55256 Mon Sep 17 00:00:00 2001 From: Nathan Faubion Date: Thu, 31 Aug 2017 12:00:29 -0700 Subject: [PATCH 1/2] AVar argument order --- bower.json | 2 +- src/Control/Monad/Aff/AVar.purs | 33 ++++++++++++++++++++++++--------- test/Test/Main.purs | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/bower.json b/bower.json index b93fb82..35eaaa8 100644 --- a/bower.json +++ b/bower.json @@ -27,7 +27,7 @@ "purescript-free": "^4.0.1", "purescript-st": "^3.0.0", "purescript-type-equality": "^2.1.0", - "purescript-avar": "^1.0.1" + "purescript-avar": "^2.0.0" }, "devDependencies": { "purescript-partial": "^1.2.0", diff --git a/src/Control/Monad/Aff/AVar.purs b/src/Control/Monad/Aff/AVar.purs index b5056cc..60ca18e 100644 --- a/src/Control/Monad/Aff/AVar.purs +++ b/src/Control/Monad/Aff/AVar.purs @@ -2,7 +2,10 @@ module Control.Monad.Aff.AVar ( module Control.Monad.Eff.AVar , makeVar , makeEmptyVar + , status , isEmptyVar + , isFilledVar + , isKilledVar , takeVar , tryTakeVar , putVar @@ -15,7 +18,7 @@ module Control.Monad.Aff.AVar import Prelude import Control.Monad.Aff (Aff, Canceler(..), makeAff) import Control.Monad.Eff (Eff) -import Control.Monad.Eff.AVar (AVar, AVAR) +import Control.Monad.Eff.AVar (AVar, AVAR, AVarStatus(..), isEmpty, isFilled, isKilled) import Control.Monad.Eff.AVar as AVar import Control.Monad.Eff.Class (liftEff) import Control.Monad.Eff.Exception (Error) @@ -32,10 +35,22 @@ makeVar = liftEff <<< AVar.makeVar makeEmptyVar ∷ ∀ eff a. Aff (avar ∷ AVAR | eff) (AVar a) makeEmptyVar = liftEff AVar.makeEmptyVar --- | Synchronously checks whether an AVar currently has a value. +-- | Synchronously checks the status of an AVar. +status ∷ ∀ eff a. AVar a → Aff (avar ∷ AVAR | eff) (AVar.AVarStatus a) +status = liftEff <<< AVar.status + +-- | Synchronously checks whether an AVar currently is empty. isEmptyVar ∷ ∀ eff a. AVar a → Aff (avar ∷ AVAR | eff) Boolean isEmptyVar = liftEff <<< AVar.isEmptyVar +-- | Synchronously checks whether an AVar currently has a value. +isFilledVar ∷ ∀ eff a. AVar a → Aff (avar ∷ AVAR | eff) Boolean +isFilledVar = liftEff <<< AVar.isFilledVar + +-- | Synchronously checks whether an AVar has been killed. +isKilledVar ∷ ∀ eff a. AVar a → Aff (avar ∷ AVAR | eff) Boolean +isKilledVar = liftEff <<< AVar.isKilledVar + -- | Takes the AVar value, leaving it empty. If the AVar is already empty, -- | the callback will be queued until the AVar is filled. Multiple takes will -- | resolve in order as the AVar fills. @@ -52,15 +67,15 @@ tryTakeVar = liftEff <<< AVar.tryTakeVar -- | Sets the value of the AVar. If the AVar is already filled, it will be -- | queued until the value is emptied. Multiple puts will resolve in order as -- | the AVar becomes available. -putVar ∷ ∀ eff a. AVar a → a → Aff (avar ∷ AVAR | eff) Unit -putVar avar value = makeAff \k → do - c ← AVar.putVar avar value k +putVar ∷ ∀ eff a. a → AVar a → Aff (avar ∷ AVAR | eff) Unit +putVar value avar = makeAff \k → do + c ← AVar.putVar value avar k pure (toCanceler c) -- | Attempts to synchronously fill an AVar. If the AVar is already filled, -- | this will do nothing. Returns true or false depending on if it succeeded. -tryPutVar ∷ ∀ eff a. AVar a → a → Aff (avar ∷ AVAR | eff) Boolean -tryPutVar avar = liftEff <<< AVar.tryPutVar avar +tryPutVar ∷ ∀ eff a. a → AVar a → Aff (avar ∷ AVAR | eff) Boolean +tryPutVar value = liftEff <<< AVar.tryPutVar value -- | Reads the AVar value. Unlike `takeVar`, this will not leave the AVar empty. -- | If the AVar is empty, this will queue until it is filled. Multiple reads @@ -77,5 +92,5 @@ tryReadVar = liftEff <<< AVar.tryReadVar -- | Kills the AVar with an exception. All pending and future actions will -- | resolve immediately with the provided exception. -killVar ∷ ∀ eff a. AVar a → Error → Aff (avar ∷ AVAR | eff) Unit -killVar avar = liftEff <<< AVar.killVar avar +killVar ∷ ∀ eff a. Error → AVar a → Aff (avar ∷ AVAR | eff) Unit +killVar error = liftEff <<< AVar.killVar error diff --git a/test/Test/Main.purs b/test/Test/Main.purs index b6930d0..d1cabe5 100644 --- a/test/Test/Main.purs +++ b/test/Test/Main.purs @@ -556,7 +556,7 @@ test_avar_order = assert "avar/order" do delay (Milliseconds 10.0) value ← takeVar var modifyRef ref (_ <> value) - putVar var "foo" + putVar "foo" var modifyRef ref (_ <> "taken") joinFiber f1 eq "takenfoo" <$> readRef ref From 104129be3fd16a1854795a5c5276ad757ccd62de Mon Sep 17 00:00:00 2001 From: Nathan Faubion Date: Thu, 31 Aug 2017 12:12:45 -0700 Subject: [PATCH 2/2] Clarify AVar examples --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cc7a1b7..c37026b 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,7 @@ The `Control.Monad.Aff.AVar` module contains asynchronous variables, which are very similar to Haskell's `MVar`. `AVar`s represent a value that is either full or empty. Calling `takeVar` on -an empty `AVar` will queue until it is filled by a matching `putVar`. +an empty `AVar` will queue until it is filled by a `putVar`. ```purescript example = do @@ -230,22 +230,23 @@ example = do > Got a value: hello ``` -Likewise, calling `putVar` will queue until it is taken: +Likewise, calling `putVar` on a filled `AVar` will queue until it is emptied by +a `takeVar`. ```purescript example = do - var <- makeEmptyVar + var <- makeVar "hello" _ <- forkAff do delay (Milliseconds 100.0) value <- takeVar var log $ "Got a value: " <> value - putVar var "hello" - log "Value taken" + putVar var "next" + log "Value put" ``` ``` (Waits 100ms) -> Value taken > Got a value: hello +> Value put ``` These combinators (and a few more) can be used as the building blocks for