@@ -2668,7 +2668,7 @@ export const scopeWith = <A, E, R>(
2668
2668
2669
2669
/* @internal */
2670
2670
export const scopedEffect = < A , E , R > ( effect : Effect . Effect < A , E , R > ) : Effect . Effect < A , E , Exclude < R , Scope . Scope > > =>
2671
- core . flatMap ( scopeMake ( ) , ( scope ) => scopeUse ( scope ) ( effect ) )
2671
+ core . flatMap ( scopeMake ( ) , ( scope ) => scopeUse ( effect , scope ) )
2672
2672
2673
2673
/* @internal */
2674
2674
export const sequentialFinalizers = < A , E , R > ( self : Effect . Effect < A , E , R > ) : Effect . Effect < A , E , R > =>
@@ -2988,96 +2988,122 @@ export const withRuntimeFlagsScoped = (
2988
2988
)
2989
2989
}
2990
2990
2991
- // circular with ReleaseMap
2991
+ // circular with Scope
2992
+
2993
+ /** @internal */
2994
+ export const scopeTag = Context . GenericTag < Scope . Scope > ( "effect/Scope" )
2992
2995
2993
2996
/* @internal */
2994
- export const releaseMapReleaseAll = (
2995
- strategy : ExecutionStrategy . ExecutionStrategy ,
2996
- exit : Exit . Exit < unknown , unknown >
2997
- ) =>
2998
- ( self : core . ReleaseMap ) : Effect . Effect < void > =>
2999
- core . suspend ( ( ) => {
3000
- switch ( self . state . _tag ) {
3001
- case "Exited" : {
2997
+ export const scope : Effect . Effect < Scope . Scope , never , Scope . Scope > = scopeTag
2998
+
2999
+ interface ScopeImpl extends Scope . CloseableScope {
3000
+ state : {
3001
+ readonly _tag : "Open"
3002
+ readonly finalizers : Set < Scope . Scope . Finalizer >
3003
+ } | {
3004
+ readonly _tag : "Closed"
3005
+ readonly exit : Exit . Exit < unknown , unknown >
3006
+ }
3007
+ }
3008
+
3009
+ const scopeUnsafeAddFinalizer = ( scope : ScopeImpl , fin : Scope . Scope . Finalizer ) : void => {
3010
+ if ( scope . state . _tag === "Open" ) {
3011
+ scope . state . finalizers . add ( fin )
3012
+ }
3013
+ }
3014
+
3015
+ const ScopeImplProto : Omit < ScopeImpl , "strategy" | "state" > = {
3016
+ [ core . ScopeTypeId ] : core . ScopeTypeId ,
3017
+ [ core . CloseableScopeTypeId ] : core . CloseableScopeTypeId ,
3018
+ pipe ( ) {
3019
+ return pipeArguments ( this , arguments )
3020
+ } ,
3021
+ fork ( this : ScopeImpl , strategy ) {
3022
+ return core . sync ( ( ) => {
3023
+ const newScope = scopeUnsafeMake ( strategy )
3024
+ if ( this . state . _tag === "Closed" ) {
3025
+ newScope . state = this . state
3026
+ return newScope
3027
+ }
3028
+ const fin = ( exit : Exit . Exit < unknown , unknown > ) => newScope . close ( exit )
3029
+ this . state . finalizers . add ( fin )
3030
+ scopeUnsafeAddFinalizer ( newScope , ( _ ) =>
3031
+ core . sync ( ( ) => {
3032
+ if ( this . state . _tag === "Open" ) {
3033
+ this . state . finalizers . delete ( fin )
3034
+ }
3035
+ } ) )
3036
+ return newScope
3037
+ } )
3038
+ } ,
3039
+ close ( this : ScopeImpl , exit ) {
3040
+ return core . suspend ( ( ) => {
3041
+ if ( this . state . _tag === "Closed" ) {
3002
3042
return core . unit
3003
3043
}
3004
- case "Running" : {
3005
- const finalizersMap = self . state . finalizers
3006
- const update = self . state . update
3007
- const finalizers = Array . from ( finalizersMap . keys ( ) ) . sort ( ( a , b ) => b - a ) . map ( ( key ) => finalizersMap . get ( key ) ! )
3008
- self . state = { _tag : "Exited" , nextKey : self . state . nextKey , exit, update }
3009
- return executionStrategy . isSequential ( strategy ) ?
3010
- pipe (
3011
- finalizers ,
3012
- core . forEachSequential ( ( fin ) => core . exit ( update ( fin ) ( exit ) ) ) ,
3013
- core . flatMap ( ( results ) =>
3014
- pipe (
3015
- core . exitCollectAll ( results ) ,
3016
- Option . map ( core . exitAsUnit ) ,
3017
- Option . getOrElse ( ( ) => core . exitUnit )
3018
- )
3044
+ const finalizers = Array . from ( this . state . finalizers . values ( ) ) . reverse ( )
3045
+ this . state = { _tag : "Closed" , exit }
3046
+ if ( finalizers . length === 0 ) {
3047
+ return core . unit
3048
+ }
3049
+ return executionStrategy . isSequential ( this . strategy ) ?
3050
+ pipe (
3051
+ core . forEachSequential ( finalizers , ( fin ) => core . exit ( fin ( exit ) ) ) ,
3052
+ core . flatMap ( ( results ) =>
3053
+ pipe (
3054
+ core . exitCollectAll ( results ) ,
3055
+ Option . map ( core . exitAsUnit ) ,
3056
+ Option . getOrElse ( ( ) => core . exitUnit )
3019
3057
)
3020
- ) :
3021
- executionStrategy . isParallel ( strategy ) ?
3022
- pipe (
3023
- forEachParUnbounded ( finalizers , ( fin ) => core . exit ( update ( fin ) ( exit ) ) , false ) ,
3024
- core . flatMap ( ( results ) =>
3025
- pipe (
3026
- core . exitCollectAll ( results , { parallel : true } ) ,
3027
- Option . map ( core . exitAsUnit ) ,
3028
- Option . getOrElse ( ( ) => core . exitUnit )
3029
- )
3058
+ )
3059
+ ) :
3060
+ executionStrategy . isParallel ( this . strategy ) ?
3061
+ pipe (
3062
+ forEachParUnbounded ( finalizers , ( fin ) => core . exit ( fin ( exit ) ) , false ) ,
3063
+ core . flatMap ( ( results ) =>
3064
+ pipe (
3065
+ core . exitCollectAll ( results , { parallel : true } ) ,
3066
+ Option . map ( core . exitAsUnit ) ,
3067
+ Option . getOrElse ( ( ) => core . exitUnit )
3030
3068
)
3031
- ) :
3032
- pipe (
3033
- forEachParN ( finalizers , strategy . parallelism , ( fin ) => core . exit ( update ( fin ) ( exit ) ) , false ) ,
3034
- core . flatMap ( ( results ) =>
3035
- pipe (
3036
- core . exitCollectAll ( results , { parallel : true } ) ,
3037
- Option . map ( core . exitAsUnit ) ,
3038
- Option . getOrElse ( ( ) => core . exitUnit )
3039
- )
3069
+ )
3070
+ ) :
3071
+ pipe (
3072
+ forEachParN ( finalizers , this . strategy . parallelism , ( fin ) => core . exit ( fin ( exit ) ) , false ) ,
3073
+ core . flatMap ( ( results ) =>
3074
+ pipe (
3075
+ core . exitCollectAll ( results , { parallel : true } ) ,
3076
+ Option . map ( core . exitAsUnit ) ,
3077
+ Option . getOrElse ( ( ) => core . exitUnit )
3040
3078
)
3041
3079
)
3080
+ )
3081
+ } )
3082
+ } ,
3083
+ addFinalizer ( this : ScopeImpl , fin ) {
3084
+ return core . suspend ( ( ) => {
3085
+ if ( this . state . _tag === "Closed" ) {
3086
+ return fin ( this . state . exit )
3042
3087
}
3043
- }
3044
- } )
3045
-
3046
- // circular with Scope
3047
-
3048
- /** @internal */
3049
- export const scopeTag = Context . GenericTag < Scope . Scope > ( "effect/Scope" )
3088
+ this . state . finalizers . add ( fin )
3089
+ return core . unit
3090
+ } )
3091
+ }
3092
+ }
3050
3093
3051
- /* @internal */
3052
- export const scope : Effect . Effect < Scope . Scope , never , Scope . Scope > = scopeTag
3094
+ const scopeUnsafeMake = (
3095
+ strategy : ExecutionStrategy . ExecutionStrategy = executionStrategy . sequential
3096
+ ) : ScopeImpl => {
3097
+ const scope = Object . create ( ScopeImplProto )
3098
+ scope . strategy = strategy
3099
+ scope . state = { _tag : "Open" , finalizers : new Set ( ) }
3100
+ return scope
3101
+ }
3053
3102
3054
3103
/* @internal */
3055
3104
export const scopeMake = (
3056
3105
strategy : ExecutionStrategy . ExecutionStrategy = executionStrategy . sequential
3057
- ) : Effect . Effect < Scope . Scope . Closeable > =>
3058
- core . map ( core . releaseMapMake , ( rm ) : Scope . Scope . Closeable => ( {
3059
- [ core . ScopeTypeId ] : core . ScopeTypeId ,
3060
- [ core . CloseableScopeTypeId ] : core . CloseableScopeTypeId ,
3061
- strategy,
3062
- pipe ( ) {
3063
- return pipeArguments ( this , arguments )
3064
- } ,
3065
- fork : ( strategy ) =>
3066
- core . uninterruptible (
3067
- pipe (
3068
- scopeMake ( strategy ) ,
3069
- core . flatMap ( ( scope ) =>
3070
- pipe (
3071
- core . releaseMapAdd ( rm , ( exit ) => core . scopeClose ( scope , exit ) ) ,
3072
- core . tap ( ( fin ) => core . scopeAddFinalizerExit ( scope , fin ) ) ,
3073
- core . as ( scope )
3074
- )
3075
- )
3076
- )
3077
- ) ,
3078
- close : ( exit ) => core . asUnit ( releaseMapReleaseAll ( strategy , exit ) ( rm ) ) ,
3079
- addFinalizer : ( fin ) => core . asUnit ( core . releaseMapAdd ( fin ) ( rm ) )
3080
- } ) )
3106
+ ) : Effect . Effect < Scope . Scope . Closeable > => core . sync ( ( ) => scopeUnsafeMake ( strategy ) )
3081
3107
3082
3108
/* @internal */
3083
3109
export const scopeExtend = dual <
0 commit comments