Skip to content

Commit

Permalink
Merge pull request #119 from natefaubion/avar-updates
Browse files Browse the repository at this point in the history
AVar updates
  • Loading branch information
natefaubion authored Aug 31, 2017
2 parents 9715ea7 + 104129b commit 46749af
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 17 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
33 changes: 24 additions & 9 deletions src/Control/Monad/Aff/AVar.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ module Control.Monad.Aff.AVar
( module Control.Monad.Eff.AVar
, makeVar
, makeEmptyVar
, status
, isEmptyVar
, isFilledVar
, isKilledVar
, takeVar
, tryTakeVar
, putVar
Expand All @@ -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)
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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
2 changes: 1 addition & 1 deletion test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 46749af

Please sign in to comment.