Skip to content

Commit 91853ea

Browse files
authored
Killing a suspended thread should be sync because laws (#121)
1 parent 2bd3ab9 commit 91853ea

File tree

3 files changed

+17
-10
lines changed

3 files changed

+17
-10
lines changed

src/Control/Monad/Aff.js

+3
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,9 @@ var Aff = function () {
608608
kill: kill,
609609
join: join,
610610
onComplete: onComplete,
611+
isSuspended: function () {
612+
return status === SUSPENDED;
613+
},
611614
run: function () {
612615
if (status === SUSPENDED) {
613616
if (!Scheduler.isDraining()) {

src/Control/Monad/Aff.purs

+10-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module Control.Monad.Aff
2727
, BracketConditions
2828
, generalBracket
2929
, nonCanceler
30+
, effCanceler
3031
, module Exports
3132
) where
3233

@@ -154,6 +155,7 @@ newtype Fiber eff a = Fiber
154155
, kill Fn.Fn2 Error (Either Error Unit Eff eff Unit) (Eff eff (Eff eff Unit))
155156
, join (Either Error a Eff eff Unit) Eff eff (Eff eff Unit)
156157
, onComplete OnComplete eff a Eff eff (Eff eff Unit)
158+
, isSuspended Eff eff Boolean
157159
}
158160

159161
instance functorFiberFunctor (Fiber eff) where
@@ -168,12 +170,14 @@ instance applicativeFiber ∷ Applicative (Fiber eff) where
168170
-- | Invokes pending cancelers in a fiber and runs cleanup effects. Blocks
169171
-- | until the fiber has fully exited.
170172
killFiber eff a. Error Fiber eff a Aff eff Unit
171-
killFiber e (Fiber t) = makeAff \k → Canceler <<< const <<< liftEff <$> Fn.runFn2 t.kill e k
173+
killFiber e (Fiber t) = liftEff t.isSuspended >>= if _
174+
then liftEff $ void $ Fn.runFn2 t.kill e (const (pure unit))
175+
else makeAff \k → effCanceler <$> Fn.runFn2 t.kill e k
172176

173177
-- | Blocks until the fiber completes, yielding the result. If the fiber
174178
-- | throws an exception, it is rethrown in the current fiber.
175179
joinFiber eff a. Fiber eff a Aff eff a
176-
joinFiber (Fiber t) = makeAff \k → Canceler <<< const <<< liftEff <$> t.join k
180+
joinFiber (Fiber t) = makeAff \k → effCanceler <$> t.join k
177181

178182
-- | A cancellation effect for actions run via `makeAff`. If a `Fiber` is
179183
-- | killed, and an async action is pending, the canceler will be called to
@@ -194,6 +198,10 @@ instance monoidCanceler ∷ Monoid (Canceler eff) where
194198
nonCanceler eff. Canceler eff
195199
nonCanceler = Canceler (const (pure unit))
196200

201+
-- | A canceler from an Eff action.
202+
effCanceler eff. Eff eff Unit Canceler eff
203+
effCanceler = Canceler <<< const <<< liftEff
204+
197205
-- | Forks an `Aff` from an `Eff` context, returning the `Fiber`.
198206
launchAff eff a. Aff eff a Eff eff (Fiber eff a)
199207
launchAff aff = do

src/Control/Monad/Aff/AVar.purs

+4-8
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,13 @@ module Control.Monad.Aff.AVar
1616
) where
1717

1818
import Prelude
19-
import Control.Monad.Aff (Aff, Canceler(..), makeAff)
20-
import Control.Monad.Eff (Eff)
19+
import Control.Monad.Aff (Aff, makeAff, effCanceler)
2120
import Control.Monad.Eff.AVar (AVar, AVAR, AVarStatus(..), isEmpty, isFilled, isKilled)
2221
import Control.Monad.Eff.AVar as AVar
2322
import Control.Monad.Eff.Class (liftEff)
2423
import Control.Monad.Eff.Exception (Error)
2524
import Data.Maybe (Maybe)
2625

27-
toCanceler eff. Eff eff Unit Canceler eff
28-
toCanceler = Canceler <<< const <<< liftEff
29-
3026
-- | Creates a fresh AVar with an initial value.
3127
makeVar eff a. a Aff (avar AVAR | eff) (AVar a)
3228
makeVar = liftEff <<< AVar.makeVar
@@ -57,7 +53,7 @@ isKilledVar = liftEff <<< AVar.isKilledVar
5753
takeVar eff a. AVar a Aff (avar AVAR | eff) a
5854
takeVar avar = makeAff \k → do
5955
c ← AVar.takeVar avar k
60-
pure (toCanceler c)
56+
pure (effCanceler c)
6157

6258
-- | Attempts to synchronously take an AVar value, leaving it empty. If the
6359
-- | AVar is empty, this will return `Nothing`.
@@ -70,7 +66,7 @@ tryTakeVar = liftEff <<< AVar.tryTakeVar
7066
putVar eff a. a AVar a Aff (avar AVAR | eff) Unit
7167
putVar value avar = makeAff \k → do
7268
c ← AVar.putVar value avar k
73-
pure (toCanceler c)
69+
pure (effCanceler c)
7470

7571
-- | Attempts to synchronously fill an AVar. If the AVar is already filled,
7672
-- | this will do nothing. Returns true or false depending on if it succeeded.
@@ -83,7 +79,7 @@ tryPutVar value = liftEff <<< AVar.tryPutVar value
8379
readVar eff a. AVar a Aff (avar AVAR | eff) a
8480
readVar avar = makeAff \k → do
8581
c ← AVar.readVar avar k
86-
pure (toCanceler c)
82+
pure (effCanceler c)
8783

8884
-- | Attempts to synchronously read an AVar. If the AVar is empty, this will
8985
-- | return `Nothing`.

0 commit comments

Comments
 (0)