@@ -16,7 +16,7 @@ data Aff eff a
16
16
| Sync (Eff eff a)
17
17
| Async ((Either Error a -> Eff eff Unit) -> Eff eff (Canceler eff))
18
18
| forall b. Catch (Error -> a) (Aff eff b) ?(b -> a)
19
- | forall b. Bracket (Aff eff b) (b -> Aff eff Unit ) (b -> Aff eff a)
19
+ | forall b. Bracket (Aff eff b) (BracketConditions eff b ) (b -> Aff eff a)
20
20
21
21
*/
22
22
var PURE = "Pure" ;
@@ -44,10 +44,11 @@ var ALT = "Alt";
44
44
var CONS = "Cons" ; // Cons-list, for stacks
45
45
var RECOVER = "Recover" ; // Continue with error handler
46
46
var RESUME = "Resume" ; // Continue indiscriminately
47
+ var BRACKETED = "Bracketed" ; // Continue with bracket finalizers
47
48
var FINALIZED = "Finalized" ; // Marker for finalization
48
49
49
- var FORKED = "Forked" ; // Reference to a forked thread , with resumption stack
50
- var THREAD = "Thread " ; // Actual thread reference
50
+ var FORKED = "Forked" ; // Reference to a forked fiber , with resumption stack
51
+ var FIBER = "Fiber " ; // Actual fiber reference
51
52
var THUNK = "Thunk" ; // Primed effect, ready to invoke
52
53
53
54
function Aff ( tag , _1 , _2 , _3 ) {
@@ -119,10 +120,10 @@ exports.makeAff = function (k) {
119
120
return new Aff ( ASYNC , k ) ;
120
121
} ;
121
122
122
- exports . bracket = function ( acquire ) {
123
- return function ( release ) {
123
+ exports . generalBracket = function ( acquire ) {
124
+ return function ( options ) {
124
125
return function ( k ) {
125
- return new Aff ( BRACKET , acquire , release , k ) ;
126
+ return new Aff ( BRACKET , acquire , options , k ) ;
126
127
} ;
127
128
} ;
128
129
} ;
@@ -199,13 +200,13 @@ function runAsync(left, eff, k) {
199
200
}
200
201
}
201
202
202
- // Thread state machine
203
+ // Fiber state machine
203
204
var BLOCKED = 0 ; // No effect is running.
204
205
var PENDING = 1 ; // An async effect is running.
205
206
var RETURN = 2 ; // The current stack has returned.
206
207
var CONTINUE = 3 ; // Run the next effect.
207
208
var BINDSTEP = 4 ; // Apply the next bind.
208
- var COMPLETED = 5 ; // The entire thread has completed.
209
+ var COMPLETED = 5 ; // The entire fiber has completed.
209
210
210
211
exports . _launchAff = function ( isLeft , fromLeft , fromRight , left , right , aff ) {
211
212
return function ( ) {
@@ -220,7 +221,7 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
220
221
var fail = null ; // Failure step
221
222
var interrupt = null ; // Asynchronous interrupt
222
223
223
- // Stack of continuations for the current thread .
224
+ // Stack of continuations for the current fiber .
224
225
var bhead = null ;
225
226
var btail = null ;
226
227
@@ -241,11 +242,11 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
241
242
var tmp , result , attempt , canceler ;
242
243
243
244
// Each invocation of `run` requires a tick. When an asynchronous effect is
244
- // resolved, we must check that the local tick coincides with the thread
245
+ // resolved, we must check that the local tick coincides with the fiber
245
246
// tick before resuming. This prevents multiple async continuations from
246
- // accidentally resuming the same thread . A common example may be invoking
247
+ // accidentally resuming the same fiber . A common example may be invoking
247
248
// the provided callback in `makeAff` more than once, but it may also be an
248
- // async effect resuming after the thread was already cancelled.
249
+ // async effect resuming after the fiber was already cancelled.
249
250
function run ( localRunTick ) {
250
251
while ( 1 ) {
251
252
tmp = null ;
@@ -372,7 +373,7 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
372
373
373
374
case RETURN :
374
375
// If the current stack has returned, and we have no other stacks to
375
- // resume or finalizers to run, the thread has halted and we can
376
+ // resume or finalizers to run, the fiber has halted and we can
376
377
// invoke all join callbacks. Otherwise we need to resume.
377
378
if ( attempts === null ) {
378
379
runTick ++ ; // Increment the counter to prevent reentry after completion.
@@ -412,14 +413,14 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
412
413
break ;
413
414
414
415
// If we have a bracket, we should enqueue the finalizer branch,
415
- // and continue with the success branch only if the thread has
416
+ // and continue with the success branch only if the fiber has
416
417
// not been interrupted. If the bracket acquisition failed, we
417
418
// should not run either.
418
419
case BRACKET :
419
420
bracket -- ;
420
421
if ( fail === null ) {
421
422
result = fromRight ( step ) ;
422
- attempts = new Aff ( CONS , attempt . _2 ( result ) , attempts . _2 ) ;
423
+ attempts = new Aff ( CONS , new Aff ( BRACKETED , attempt . _2 , result ) , attempts . _2 ) ;
423
424
if ( interrupt === null || bracket > 0 ) {
424
425
status = CONTINUE ;
425
426
step = attempt . _3 ( result ) ;
@@ -429,6 +430,19 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
429
430
}
430
431
break ;
431
432
433
+ case BRACKETED :
434
+ bracket ++ ;
435
+ attempts = new Aff ( CONS , new Aff ( FINALIZED , step ) , attempts . _2 ) ;
436
+ status = CONTINUE ;
437
+ if ( interrupt !== null ) {
438
+ step = attempt . _1 . kill ( fromLeft ( interrupt ) ) ( attempt . _2 ) ;
439
+ } else if ( fail !== null ) {
440
+ step = attempt . _1 . throw ( fromLeft ( fail ) ) ( attempt . _2 ) ;
441
+ } else {
442
+ step = attempt . _1 . release ( attempt . _2 ) ;
443
+ }
444
+ break ;
445
+
432
446
case FINALIZED :
433
447
bracket -- ;
434
448
attempts = attempts . _2 ;
@@ -455,11 +469,11 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
455
469
}
456
470
}
457
471
joins = tmp ;
458
- // If we have an unhandled exception, and no other thread has joined
472
+ // If we have an unhandled exception, and no other fiber has joined
459
473
// then we need to throw the exception in a fresh stack.
460
474
if ( isLeft ( step ) && ! joins ) {
461
475
setTimeout ( function ( ) {
462
- // Guard on joins because a completely synchronous thread can
476
+ // Guard on joins because a completely synchronous fiber can
463
477
// still have an observer.
464
478
if ( ! joins ) {
465
479
throw fromLeft ( step ) ;
@@ -554,9 +568,9 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
554
568
555
569
exports . _sequential = function ( isLeft , fromLeft , fromRight , left , right , runAff , par ) {
556
570
function runParAff ( cb ) {
557
- // Table of all forked threads .
558
- var threadId = 0 ;
559
- var threads = { } ;
571
+ // Table of all forked fibers .
572
+ var fiberId = 0 ;
573
+ var fibers = { } ;
560
574
561
575
// Table of currently running cancelers, as a product of `Alt` behavior.
562
576
var killId = 0 ;
@@ -572,7 +586,7 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
572
586
var root = EMPTY ;
573
587
574
588
// Walks a tree, invoking all the cancelers. Returns the table of pending
575
- // cancellation threads .
589
+ // cancellation fibers .
576
590
function kill ( error , par , cb ) {
577
591
var step = par ;
578
592
var fail = null ;
@@ -587,22 +601,22 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
587
601
588
602
switch ( step . tag ) {
589
603
case FORKED :
590
- tmp = threads [ step . _1 ] ;
591
- // If we haven't forked the thread yet (such as with a sync Alt),
604
+ tmp = fibers [ step . _1 ] ;
605
+ // If we haven't forked the fiber yet (such as with a sync Alt),
592
606
// then we should just remove it from the queue and continue.
593
607
if ( tmp . tag === THUNK ) {
594
- delete threads [ step . _1 ] ;
608
+ delete fibers [ step . _1 ] ;
595
609
cb ( right ( void 0 ) ) ( ) ;
596
610
} else {
597
611
// Again, we prime the effect but don't run it yet, so that we can
598
- // collect all the threads first.
612
+ // collect all the fibers first.
599
613
kills [ count ++ ] = runAff ( function ( result ) {
600
614
return function ( ) {
601
615
count -- ;
602
616
if ( fail === null && isLeft ( result ) ) {
603
617
fail = result ;
604
618
}
605
- // We can resolve the callback when all threads have died.
619
+ // We can resolve the callback when all fibers have died.
606
620
if ( count === 0 ) {
607
621
cb ( fail || right ( void 0 ) ) ( ) ;
608
622
}
@@ -646,7 +660,7 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
646
660
return kills ;
647
661
}
648
662
649
- // When a thread resolves, we need to bubble back up the tree with the
663
+ // When a fiber resolves, we need to bubble back up the tree with the
650
664
// result, computing the applicative nodes.
651
665
function join ( result , head , tail ) {
652
666
var fail , step , lhs , rhs , tmp , kid ;
@@ -758,12 +772,12 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
758
772
}
759
773
}
760
774
761
- function resolve ( thread ) {
775
+ function resolve ( fiber ) {
762
776
return function ( result ) {
763
777
return function ( ) {
764
- delete threads [ thread . _1 ] ;
765
- thread . _3 = result ;
766
- join ( result , thread . _2 . _1 , thread . _2 . _2 ) ;
778
+ delete fibers [ fiber . _1 ] ;
779
+ fiber . _3 = result ;
780
+ join ( result , fiber . _2 . _1 , fiber . _2 . _2 ) ;
767
781
} ;
768
782
} ;
769
783
}
@@ -779,11 +793,11 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
779
793
var step = par ;
780
794
var head = null ;
781
795
var tail = null ;
782
- var tmp , tid ;
796
+ var tmp , fid ;
783
797
784
798
loop: while ( 1 ) {
785
799
tmp = null ;
786
- tid = null ;
800
+ fid = null ;
787
801
788
802
switch ( status ) {
789
803
case CONTINUE :
@@ -811,17 +825,17 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
811
825
break ;
812
826
default :
813
827
// When we hit a leaf value, we suspend the stack in the `FORKED`.
814
- // When the thread resolves, it can bubble back up the tree.
815
- tid = threadId ++ ;
828
+ // When the fiber resolves, it can bubble back up the tree.
829
+ fid = fiberId ++ ;
816
830
status = RETURN ;
817
831
tmp = step ;
818
- step = new Aff ( FORKED , tid , new Aff ( CONS , head , tail ) , EMPTY ) ;
832
+ step = new Aff ( FORKED , fid , new Aff ( CONS , head , tail ) , EMPTY ) ;
819
833
// We prime the effect, but don't immediately run it. We need to
820
834
// walk the entire tree first before actually running effects
821
835
// because they may all be synchronous and resolve immediately, at
822
836
// which point it would attempt to resolve against an incomplete
823
837
// tree.
824
- threads [ tid ] = new Aff ( THUNK , runAff ( resolve ( step ) ) ( tmp ) ) ;
838
+ fibers [ fid ] = new Aff ( THUNK , runAff ( resolve ( step ) ) ( tmp ) ) ;
825
839
}
826
840
break ;
827
841
case RETURN :
@@ -852,12 +866,12 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
852
866
// Keep a reference to the tree root so it can be cancelled.
853
867
root = step ;
854
868
855
- // Walk the primed threads and fork them. We store the actual `Thread `
869
+ // Walk the primed fibers and fork them. We store the actual `Fiber `
856
870
// reference so we can cancel them when needed.
857
- for ( tid = 0 ; tid < threadId ; tid ++ ) {
858
- tmp = threads [ tid ] ;
871
+ for ( fid = 0 ; fid < fiberId ; fid ++ ) {
872
+ tmp = fibers [ fid ] ;
859
873
if ( tmp && tmp . tag === THUNK ) {
860
- threads [ tid ] = new Aff ( THREAD , tmp . _1 ( ) ) ;
874
+ fibers [ fid ] = new Aff ( FIBER , tmp . _1 ( ) ) ;
861
875
}
862
876
}
863
877
}
@@ -872,7 +886,7 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
872
886
function cancel ( error , cb ) {
873
887
interrupt = left ( error ) ;
874
888
875
- // We can drop the threads here because we are only canceling join
889
+ // We can drop the fibers here because we are only canceling join
876
890
// attempts, which are synchronous anyway.
877
891
for ( var kid = 0 , n = killId ; kid < n ; kid ++ ) {
878
892
runAff ( ignore , kills [ kid ] . kill ( error ) ) ( ) ;
0 commit comments