Skip to content

Commit

Permalink
Move autoClose for Resource to common (#3483)
Browse files Browse the repository at this point in the history
  • Loading branch information
serras authored Sep 10, 2024
1 parent 3521236 commit a021927
Show file tree
Hide file tree
Showing 19 changed files with 140 additions and 89 deletions.
4 changes: 0 additions & 4 deletions arrow-libs/core/arrow-autoclose/api/arrow-autoclose.api
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ public final class arrow/AutoCloseScopeKt {
public static final fun autoCloseScope (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

public final class arrow/AutoCloseableExtensionsKt {
public static final fun install (Larrow/AutoCloseScope;Ljava/lang/AutoCloseable;)Ljava/lang/AutoCloseable;
}

public final class arrow/DefaultAutoCloseScope : arrow/AutoCloseScope {
public fun <init> ()V
public fun autoClose (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
Expand Down
1 change: 0 additions & 1 deletion arrow-libs/core/arrow-autoclose/knit.code.include
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package ${knit.package}.${knit.name}

import arrow.AutoCloseScope
import arrow.autoCloseScope
import arrow.install

public class Scanner(
private val path: String,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package arrow.autocloseable.examples.exampleAutocloseable01

import arrow.AutoCloseScope
import arrow.autoCloseScope
import arrow.install

public class Scanner(
private val path: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package arrow.autocloseable.examples.exampleAutocloseable02

import arrow.AutoCloseScope
import arrow.autoCloseScope
import arrow.install

public class Scanner(
private val path: String,
Expand Down
8 changes: 4 additions & 4 deletions arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,6 @@ public abstract interface annotation class arrow/fx/coroutines/ResourceDSL : jav
}

public final class arrow/fx/coroutines/ResourceExtensionsKt {
public static final fun autoCloseable (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun autoCloseable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2;
public static synthetic fun autoCloseable$default (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun autoCloseable$default (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function2;
public static final fun closeable (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun closeable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2;
public static synthetic fun closeable$default (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
Expand All @@ -238,6 +234,10 @@ public final class arrow/fx/coroutines/ResourceExtensionsKt {
public final class arrow/fx/coroutines/ResourceKt {
public static final fun allocated (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun asFlow (Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
public static final fun autoCloseable (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun autoCloseable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2;
public static synthetic fun autoCloseable$default (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun autoCloseable$default (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function2;
public static final fun resource (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2;
public static final fun resource (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2;
public static final fun resourceScope (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ final fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).arrow.fx.coroutin
final fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).arrow.fx.coroutines/repeat(): kotlinx.coroutines.flow/Flow<#A> // arrow.fx.coroutines/repeat|repeat@kotlinx.coroutines.flow.Flow<0:0>(){0§<kotlin.Any?>}[0]
final fun <#A: kotlin/Any?> arrow.fx.coroutines/resource(kotlin.coroutines/SuspendFunction0<#A>, kotlin.coroutines/SuspendFunction2<#A, arrow.fx.coroutines/ExitCase, kotlin/Unit>): kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ResourceScope, #A> // arrow.fx.coroutines/resource|resource(kotlin.coroutines.SuspendFunction0<0:0>;kotlin.coroutines.SuspendFunction2<0:0,arrow.fx.coroutines.ExitCase,kotlin.Unit>){0§<kotlin.Any?>}[0]
final fun <#A: kotlin/Any?> arrow.fx.coroutines/resource(kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ResourceScope, #A>): kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ResourceScope, #A> // arrow.fx.coroutines/resource|resource(kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ResourceScope,0:0>){0§<kotlin.Any?>}[0]
final fun <#A: kotlin/AutoCloseable> arrow.fx.coroutines/autoCloseable(kotlinx.coroutines/CoroutineDispatcher = ..., kotlin.coroutines/SuspendFunction0<#A>): kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ResourceScope, #A> // arrow.fx.coroutines/autoCloseable|autoCloseable(kotlinx.coroutines.CoroutineDispatcher;kotlin.coroutines.SuspendFunction0<0:0>){0§<kotlin.AutoCloseable>}[0]
final fun arrow.fx.coroutines/fixedRate(kotlin.time/Duration, kotlin/Boolean = ..., kotlin/Function0<kotlin.time/ComparableTimeMark> = ...): kotlinx.coroutines.flow/Flow<kotlin/Unit> // arrow.fx.coroutines/fixedRate|fixedRate(kotlin.time.Duration;kotlin.Boolean;kotlin.Function0<kotlin.time.ComparableTimeMark>){}[0]
final fun arrow.fx.coroutines/fixedRate(kotlin/Long, kotlin/Boolean = ..., kotlin/Function0<kotlin.time/ComparableTimeMark> = ...): kotlinx.coroutines.flow/Flow<kotlin/Unit> // arrow.fx.coroutines/fixedRate|fixedRate(kotlin.Long;kotlin.Boolean;kotlin.Function0<kotlin.time.ComparableTimeMark>){}[0]
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).arrow.fx.coroutines/mapIndexed(crossinline kotlin.coroutines/SuspendFunction2<kotlin/Int, #A, #B>): kotlinx.coroutines.flow/Flow<#B> // arrow.fx.coroutines/mapIndexed|mapIndexed@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction2<kotlin.Int,0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
Expand All @@ -166,6 +167,7 @@ final suspend fun <#A: kotlin/Any?> (kotlin.coroutines/SuspendFunction1<arrow.fx
final suspend fun <#A: kotlin/Any?> (kotlinx.coroutines/CoroutineScope).arrow.fx.coroutines.await/awaitAll(kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines.await/AwaitAllScope, #A>): #A // arrow.fx.coroutines.await/awaitAll|awaitAll@kotlinx.coroutines.CoroutineScope(kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.await.AwaitAllScope,0:0>){0§<kotlin.Any?>}[0]
final suspend fun <#A: kotlin/Any?> arrow.fx.coroutines.await/awaitAll(kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines.await/AwaitAllScope, #A>): #A // arrow.fx.coroutines.await/awaitAll|awaitAll(kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.await.AwaitAllScope,0:0>){0§<kotlin.Any?>}[0]
final suspend fun <#A: kotlin/Any?> arrow.fx.coroutines/resourceScope(kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ResourceScope, #A>): #A // arrow.fx.coroutines/resourceScope|resourceScope(kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ResourceScope,0:0>){0§<kotlin.Any?>}[0]
final suspend fun <#A: kotlin/AutoCloseable> (arrow.fx.coroutines/ResourceScope).arrow.fx.coroutines/autoCloseable(kotlinx.coroutines/CoroutineDispatcher = ..., kotlin.coroutines/SuspendFunction0<#A>): #A // arrow.fx.coroutines/autoCloseable|autoCloseable@arrow.fx.coroutines.ResourceScope(kotlinx.coroutines.CoroutineDispatcher;kotlin.coroutines.SuspendFunction0<0:0>){0§<kotlin.AutoCloseable>}[0]
final suspend fun arrow.fx.coroutines/cancelAndCompose(kotlinx.coroutines/Deferred<*>, kotlinx.coroutines/Deferred<*>) // arrow.fx.coroutines/cancelAndCompose|cancelAndCompose(kotlinx.coroutines.Deferred<*>;kotlinx.coroutines.Deferred<*>){}[0]
final suspend inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?> (arrow.core.raise/Raise<#A>).arrow.fx.coroutines/parZipOrAccumulate(crossinline kotlin/Function2<#A, #A, #A>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #B>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #C>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #D>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #E>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #F>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #G>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #H>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #I>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #J>, crossinline kotlin.coroutines/SuspendFunction10<kotlinx.coroutines/CoroutineScope, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K>): #K // arrow.fx.coroutines/parZipOrAccumulate|parZipOrAccumulate@arrow.core.raise.Raise<0:0>(kotlin.Function2<0:0,0:0,0:0>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:1>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:2>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:3>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:4>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:5>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:6>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:7>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:8>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:9>;kotlin.coroutines.SuspendFunction10<kotlinx.coroutines.CoroutineScope,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>;3§<kotlin.Any?>;4§<kotlin.Any?>;5§<kotlin.Any?>;6§<kotlin.Any?>;7§<kotlin.Any?>;8§<kotlin.Any?>;9§<kotlin.Any?>;10§<kotlin.Any?>}[0]
final suspend inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?> (arrow.core.raise/Raise<#A>).arrow.fx.coroutines/parZipOrAccumulate(kotlin.coroutines/CoroutineContext, crossinline kotlin/Function2<#A, #A, #A>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #B>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #C>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #D>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #E>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #F>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #G>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #H>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #I>, crossinline kotlin.coroutines/SuspendFunction1<arrow.fx.coroutines/ScopedRaiseAccumulate<#A>, #J>, crossinline kotlin.coroutines/SuspendFunction10<kotlinx.coroutines/CoroutineScope, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K>): #K // arrow.fx.coroutines/parZipOrAccumulate|parZipOrAccumulate@arrow.core.raise.Raise<0:0>(kotlin.coroutines.CoroutineContext;kotlin.Function2<0:0,0:0,0:0>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:1>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:2>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:3>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:4>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:5>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:6>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:7>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:8>;kotlin.coroutines.SuspendFunction1<arrow.fx.coroutines.ScopedRaiseAccumulate<0:0>,0:9>;kotlin.coroutines.SuspendFunction10<kotlinx.coroutines.CoroutineScope,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>;3§<kotlin.Any?>;4§<kotlin.Any?>;5§<kotlin.Any?>;6§<kotlin.Any?>;7§<kotlin.Any?>;8§<kotlin.Any?>;9§<kotlin.Any?>;10§<kotlin.Any?>}[0]
Expand Down
1 change: 1 addition & 0 deletions arrow-libs/fx/arrow-fx-coroutines/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ kotlin {
commonTest {
dependencies {
implementation(projects.arrowCore)
implementation(projects.arrowAtomic)
implementation(libs.kotlin.test)
implementation(libs.coroutines.test)
implementation(libs.kotest.assertionsCore)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ import arrow.atomic.Atomic
import arrow.atomic.value
import arrow.core.identity
import arrow.core.prependTo
import arrow.fx.coroutines.ExitCase.Cancelled
import arrow.fx.coroutines.ExitCase.Companion.ExitCase
import arrow.fx.coroutines.ExitCase.Completed
import arrow.fx.coroutines.ExitCase.Failure
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -517,9 +514,9 @@ private value class ResourceScopeImpl(
acquire().also { a ->
val finalizer: suspend (ExitCase) -> Unit = { exitCase ->
val errorOrNull = when (exitCase) {
Completed -> null
is Cancelled -> exitCase.exception
is Failure -> exitCase.failure
ExitCase.Completed -> null
is ExitCase.Cancelled -> exitCase.exception
is ExitCase.Failure -> exitCase.failure
}
release(a, errorOrNull)
}
Expand All @@ -536,3 +533,36 @@ private value class ResourceScopeImpl(
} ?: acc
}
}

/** Platform-dependent IO [CoroutineDispatcher] **/
internal expect val IODispatcher: CoroutineDispatcher

/**
* Creates a [Resource] from an [AutoCloseable], which uses [AutoCloseable.close] for releasing.
*
* ```kotlin
* import arrow.fx.coroutines.resourceScope
* import arrow.fx.coroutines.autoCloseable
* import java.io.FileInputStream
*
* suspend fun copyFile(src: String, dest: String): Unit =
* resourceScope {
* val a: FileInputStream = autoCloseable { FileInputStream(src) }
* val b: FileInputStream = autoCloseable { FileInputStream(dest) }
* /** read from [a] and write to [b]. **/
* } // Both resources will be closed accordingly to their #close methods
* ```
* <!--- KNIT example-resource-10.kt -->
*/
@ResourceDSL
public suspend fun <A : AutoCloseable> ResourceScope.autoCloseable(
closingDispatcher: CoroutineDispatcher = IODispatcher,
autoCloseable: suspend () -> A,
): A = install({ autoCloseable() } ) { s: A, _: ExitCase -> withContext(closingDispatcher) { s.close() } }

public fun <A : AutoCloseable> autoCloseable(
closingDispatcher: CoroutineDispatcher = IODispatcher,
autoCloseable: suspend () -> A,
): Resource<A> = resource {
autoCloseable(closingDispatcher, autoCloseable)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package arrow.fx.coroutines

import arrow.atomic.AtomicBoolean
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.matchers.shouldBe
import io.kotest.property.Arb
import io.kotest.property.checkAll
import kotlinx.coroutines.test.runTest
import kotlin.test.Test

class ResourceAutoCloseTest {

class AutoCloseableTest : AutoCloseable {
val didClose = AtomicBoolean(false)
override fun close() = didClose.set(true)
}

@Test
fun autoCloseableCloses() = runTest {
val t = AutoCloseableTest()
resourceScope {
autoCloseable { t }
}

t.didClose.get() shouldBe true
}

@Test
fun autoCloseableClosesOnError() = runTest {
checkAll(10, Arb.throwable()) { throwable ->
val t = AutoCloseableTest()

shouldThrow<Exception> {
resourceScope {
autoCloseable { t }
throw throwable
}
} shouldBe throwable

t.didClose.get() shouldBe true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package arrow.fx.coroutines

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

internal actual val IODispatcher: CoroutineDispatcher = Dispatchers.Main
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlin.time.Duration

internal actual val IODispatcher: CoroutineDispatcher = Dispatchers.IO

/**
* Creates a single threaded [CoroutineContext] as a [Resource].
* Upon release an orderly shutdown of the [ExecutorService] takes place in which previously submitted
Expand Down Expand Up @@ -99,36 +101,6 @@ public fun <A : Closeable> closeable(
closeable(closingDispatcher, closeable)
}

/**
* Creates a [Resource] from an [AutoCloseable], which uses [AutoCloseable.close] for releasing.
*
* ```kotlin
* import arrow.fx.coroutines.resourceScope
* import arrow.fx.coroutines.autoCloseable
* import java.io.FileInputStream
*
* suspend fun copyFile(src: String, dest: String): Unit =
* resourceScope {
* val a: FileInputStream = autoCloseable { FileInputStream(src) }
* val b: FileInputStream = autoCloseable { FileInputStream(dest) }
* /** read from [a] and write to [b]. **/
* } // Both resources will be closed accordingly to their #close methods
* ```
* <!--- KNIT example-resourceextensions-03.kt -->
*/
@ResourceDSL
public suspend fun <A : AutoCloseable> ResourceScope.autoCloseable(
closingDispatcher: CoroutineDispatcher = Dispatchers.IO,
autoCloseable: suspend () -> A,
): A = install({ autoCloseable() } ) { s: A, _: ExitCase -> withContext(closingDispatcher) { s.close() } }

public fun <A : AutoCloseable> autoCloseable(
closingDispatcher: CoroutineDispatcher = Dispatchers.IO,
autoCloseable: suspend () -> A,
): Resource<A> = resource {
autoCloseable(closingDispatcher, autoCloseable)
}

/**
* Creates a single threaded [CoroutineContext] as a [Resource].
* Upon release an orderly shutdown of the [ExecutorService] takes place in which previously submitted
Expand All @@ -150,7 +122,7 @@ public fun <A : AutoCloseable> autoCloseable(
* ```text
* I am running on single
* ```
* <!--- KNIT example-resourceextensions-04.kt -->
* <!--- KNIT example-resourceextensions-03.kt -->
*/
@OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class)
@ResourceDSL
Expand Down Expand Up @@ -181,7 +153,7 @@ public fun singleThreadContext(name: String): Resource<ExecutorCoroutineDispatch
* ```text
* I am running on custom-pool-1
* ```
* <!--- KNIT example-resourceextensions-05.kt -->
* <!--- KNIT example-resourceextensions-04.kt -->
*/
@OptIn(DelicateCoroutinesApi::class)
@ResourceDSL
Expand Down
Loading

0 comments on commit a021927

Please sign in to comment.