Skip to content

Commit

Permalink
Merge branch 'main' into arrow-v2.0.0-beta.1
Browse files Browse the repository at this point in the history
  • Loading branch information
ShreckYe committed Dec 4, 2024
2 parents 4f302f0 + f22a943 commit 0c919c1
Show file tree
Hide file tree
Showing 39 changed files with 403 additions and 706 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Change log

## v0.6.0 / 2024-11-29

* add conversion functions to convert Vert.x `Buffer`s to kotlinx-io `RawSink`s and `Sink`s and Okio `Sink`s and `BufferedSink`s

The `Source` conversion functions are not provided because Vert.x `Buffer` doesn't provide reading methods with a reader index.

* adapt to the [Exposed SELECT DSL design changes](https://github.com/JetBrains/Exposed/pull/1916) and bump Exposed to v0.56.0

The old `deleteWhereStatement` that conflicts with the new one is removed, causing a source and binary incompatible change.

* add API documentation generated by Dokka hosted at <https://huanshankeji.github.io/kotlin-common/>
* add CODE_OF_CONDUCT.md and CONTRIBUTING.md
* use the Kotlin binary compatibility validator
* add some experimental plus operators for nullable functions/lambdas
* add some common functions for Exposed and Vert.x SQL Client such as `jdbcUrl`, `ClientBuilder<*>.withCoConnectHandler`, and `SqlConnectOptions.setUpConventionally`
* add a `CoroutineAutoCloseable` interface like `AutoCloseable` and its version of the `use` extension function

## v0.5.1 / 2024-10-19

* enable the iOS targets for the "coroutines" module, which was disabled due to a compiler bug
Expand Down
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,10 @@ apiValidation {
klib {
enabled = true
}

ignoredProjects += "kotlin-common".let {
"$it-serialization-benchmark".let {
listOf(it, "$it-jvm-only")
} + "$it-vertx-with-context-receivers"
}
}
4 changes: 2 additions & 2 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ repositories {

dependencies {
// With Kotlin 2.0.20, a "Could not parse POM" build error occurs in the JVM projects of some dependent projects.
implementation(kotlin("gradle-plugin", "2.0.10"))
implementation(kotlin("gradle-plugin", "2.1.0"))
implementation("com.huanshankeji:common-gradle-dependencies:0.8.0-20241016") // don't use a snapshot version in a main branch
implementation("com.huanshankeji.team:gradle-plugins:0.6.0") // don't use a snapshot version in a main branch
implementation("com.huanshankeji.team:gradle-plugins:0.8.0") // don't use a snapshot version in a main branch
implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.0.0-Beta")
}
4 changes: 4 additions & 0 deletions buildSrc/src/main/kotlin/OptIns.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
val optIns = listOf("com.huanshankeji.InternalApi", "com.huanshankeji.ExperimentalApi")

inline fun forEachOptIn(action: (String) -> Unit) =
optIns.forEach(action)
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/VersionsAndDependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import com.huanshankeji.CommonDependencies
import com.huanshankeji.CommonGradleClasspathDependencies
import com.huanshankeji.CommonVersions

val projectVersion = "0.6.0-SNAPSHOT"
val projectVersion = "0.6.1-SNAPSHOT"

val commonVersions = CommonVersions(arrow = "2.0.0-rc.1") // for Wasm JS
val commonVersions = CommonVersions(arrow = "2.0.0-rc.1" /* for Wasm JS*/, exposed = "0.56.0")
val commonDependencies = CommonDependencies(commonVersions)
val commonGradleClasspathDependencies = CommonGradleClasspathDependencies(commonVersions)

Expand Down
3 changes: 1 addition & 2 deletions buildSrc/src/main/kotlin/common-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ plugins {
id("com.huanshankeji.team.with-group")
id("maven-central")
id("com.huanshankeji.team.default-github-packages-maven-publish")
id("version")
id("dokka-convention")
}

version = projectVersion

afterEvaluate {
publishing.publications.withType<MavenPublication> {
pomForTeamDefaultOpenSource(
Expand Down
13 changes: 1 addition & 12 deletions buildSrc/src/main/kotlin/dokka-convention.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
plugins {
id("org.jetbrains.dokka")
id("com.huanshankeji.team.dokka.github-dokka-convention")
}

dokka {
//moduleName.set("Huanshankeji Kotlin Common")
dokkaSourceSets.all {
//includes.from("README.md")
sourceLink {
//localDirectory.set(file("src/main/kotlin"))
remoteUrl(
"https://github.com/huanshankeji/kotlin-common/tree/v${version}/${
with(project) {
name.removePrefix(parent!!.name + '-')
}
}"
)
remoteLineSuffix.set("#L")
}
/*pluginsConfiguration.html {
footerMessage.set("(c) Yongshun Ye")
}*/
Expand Down
6 changes: 6 additions & 0 deletions buildSrc/src/main/kotlin/jvm-conventions.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask

plugins {
id("common-conventions")
id("com.huanshankeji.kotlin-jvm-library-sonatype-ossrh-publish-conventions")
}

kotlin.jvmToolchain(8)

tasks.named<KotlinCompilationTask<*>>("compileKotlin").configure {
forEachOptIn { compilerOptions.freeCompilerArgs.add("-opt-in=$it") }
}
6 changes: 6 additions & 0 deletions buildSrc/src/main/kotlin/multiplatform-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ kotlin {

@OptIn(ExperimentalWasmDsl::class)
wasmJs()

sourceSets {
all {
forEachOptIn(languageSettings::optIn)
}
}
}
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/version.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// extracted into a separate script so the version can be set before `dokka-convention`

version = projectVersion
22 changes: 22 additions & 0 deletions core/api/kotlin-common-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ public abstract interface class com/huanshankeji/BidirectionalConversion {
public abstract fun to (Ljava/lang/Object;)Ljava/lang/Object;
}

public abstract interface annotation class com/huanshankeji/ExperimentalApi : java/lang/annotation/Annotation {
}

public final class com/huanshankeji/FunctionImplementationRemovedKt {
public static final fun functionImplementationRemoved ()Ljava/lang/Void;
}

public abstract interface annotation class com/huanshankeji/InternalApi : java/lang/annotation/Annotation {
}

public final class com/huanshankeji/LambdasKt {
public static final fun emptyLambda ()Lkotlin/jvm/functions/Function0;
public static final fun lambdaOf (Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function0;
Expand Down Expand Up @@ -45,6 +55,10 @@ public final class com/huanshankeji/collections/LexicographicOrderListComparable
public static final fun lexicographicOrderComparable (Ljava/util/List;)Lcom/huanshankeji/collections/LexicographicOrderListComparable;
}

public final class com/huanshankeji/jdbc/JdbcUrlsKt {
public static final fun jdbcUrl (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;)Ljava/lang/String;
}

public final class com/huanshankeji/kotlin/CallbacksKt {
public static final fun produceInCallback (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}
Expand All @@ -58,6 +72,14 @@ public final class com/huanshankeji/kotlin/UseKt {
public static final fun use (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

public final class com/huanshankeji/kotlin/function/parametertypeparameter/NullableUnitReturnTypeParameterFunctionKt {
public static final fun plus (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
}

public final class com/huanshankeji/kotlin/function/receivertypeparameter/NullableUnitReturnTypeReceiverFunctionKt {
public static final fun plus (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
}

public final class com/huanshankeji/os/OSKt {
public static final fun getCurrentOS ()Lcom/huanshankeji/os/Os;
public static final fun getSystemOsName ()Ljava/lang/String;
Expand Down
11 changes: 11 additions & 0 deletions core/api/kotlin-common-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
// - Show declarations: true

// Library unique name: <com.huanshankeji:kotlin-common-core>
open annotation class com.huanshankeji/ExperimentalApi : kotlin/Annotation { // com.huanshankeji/ExperimentalApi|null[0]
constructor <init>() // com.huanshankeji/ExperimentalApi.<init>|<init>(){}[0]
}

open annotation class com.huanshankeji/InternalApi : kotlin/Annotation { // com.huanshankeji/InternalApi|null[0]
constructor <init>() // com.huanshankeji/InternalApi.<init>|<init>(){}[0]
}

open annotation class com.huanshankeji/Untested : kotlin/Annotation { // com.huanshankeji/Untested|null[0]
constructor <init>() // com.huanshankeji/Untested.<init>|<init>(){}[0]
}
Expand Down Expand Up @@ -64,6 +72,7 @@ final fun <#A: kotlin/Any?> (kotlin.sequences/Sequence<#A>).com.huanshankeji.seq
final fun <#A: kotlin/Comparable<#A>> (kotlin.collections/List<#A>).com.huanshankeji.collections/lexicographicOrderComparable(): com.huanshankeji.collections/LexicographicOrderListComparable<#A> // com.huanshankeji.collections/lexicographicOrderComparable|[email protected]<0:0>(){0§<kotlin.Comparable<0:0>>}[0]
final fun <#A: kotlin/Enum<#A>> com.huanshankeji.kotlin/enumPlus(kotlin/Array<#A>, #A, kotlin/Int): #A // com.huanshankeji.kotlin/enumPlus|enumPlus(kotlin.Array<0:0>;0:0;kotlin.Int){0§<kotlin.Enum<0:0>>}[0]
final fun com.huanshankeji.codec/uLongBigEndianShiftOffset(kotlin/Int): kotlin/Int // com.huanshankeji.codec/uLongBigEndianShiftOffset|uLongBigEndianShiftOffset(kotlin.Int){}[0]
final fun com.huanshankeji/functionImplementationRemoved(): kotlin/Nothing // com.huanshankeji/functionImplementationRemoved|functionImplementationRemoved(){}[0]
final inline fun <#A: kotlin/Any> com.huanshankeji.kotlin/produceInCallback(kotlin/Function1<kotlin/Function1<#A, kotlin/Unit>, kotlin/Unit>): #A // com.huanshankeji.kotlin/produceInCallback|produceInCallback(kotlin.Function1<kotlin.Function1<0:0,kotlin.Unit>,kotlin.Unit>){0§<kotlin.Any>}[0]
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (#A).com.huanshankeji.kotlin/use(kotlin/Function1<#A, #B>, kotlin/Function1<#A, kotlin/Unit>): #B // com.huanshankeji.kotlin/use|use@0:0(kotlin.Function1<0:0,0:1>;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> com.huanshankeji/lambdaOf(noinline kotlin/Function1<#A, #B>): kotlin/Function1<#A, #B> // com.huanshankeji/lambdaOf|lambdaOf(kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
Expand All @@ -72,6 +81,8 @@ final inline fun <#A: kotlin/Any?, #B: kotlin/Comparable<#B>> (kotlin.collection
final inline fun <#A: kotlin/Any?, #B: kotlin/Comparable<#B>> (kotlin.sequences/Sequence<#A>).com.huanshankeji.sequences/isSortedBy(crossinline kotlin/Function1<#A, #B?>): kotlin/Boolean // com.huanshankeji.sequences/isSortedBy|[email protected]<0:0>(kotlin.Function1<0:0,0:1?>){0§<kotlin.Any?>;1§<kotlin.Comparable<0:1>>}[0]
final inline fun <#A: kotlin/Any?, #B: kotlin/Comparable<#B>> (kotlin.sequences/Sequence<#A>).com.huanshankeji.sequences/isSortedByDescending(crossinline kotlin/Function1<#A, #B?>): kotlin/Boolean // com.huanshankeji.sequences/isSortedByDescending|[email protected]<0:0>(kotlin.Function1<0:0,0:1?>){0§<kotlin.Any?>;1§<kotlin.Comparable<0:1>>}[0]
final inline fun <#A: kotlin/Any?> (#A).com.huanshankeji.kotlin/closeFinally(kotlin/Throwable?, kotlin/Function1<#A, kotlin/Unit>) // com.huanshankeji.kotlin/closeFinally|closeFinally@0:0(kotlin.Throwable?;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
final inline fun <#A: kotlin/Any?> (kotlin/Function1<#A, kotlin/Unit>?).com.huanshankeji.kotlin.function.parametertypeparameter/plus(noinline kotlin/Function1<#A, kotlin/Unit>?): kotlin/Function1<#A, kotlin/Unit>? // com.huanshankeji.kotlin.function.parametertypeparameter/plus|[email protected]<0:0,kotlin.Unit>?(kotlin.Function1<0:0,kotlin.Unit>?){0§<kotlin.Any?>}[0]
final inline fun <#A: kotlin/Any?> (kotlin/Function1<#A, kotlin/Unit>?).com.huanshankeji.kotlin.function.receivertypeparameter/plus(noinline kotlin/Function1<#A, kotlin/Unit>?): kotlin/Function1<#A, kotlin/Unit>? // com.huanshankeji.kotlin.function.receivertypeparameter/plus|[email protected]<0:0,kotlin.Unit>?(kotlin.Function1<0:0,kotlin.Unit>?){0§<kotlin.Any?>}[0]
final inline fun <#A: kotlin/Comparable<#A>> (kotlin.collections/Iterable<#A>).com.huanshankeji.collections/isSorted(): kotlin/Boolean // com.huanshankeji.collections/isSorted|[email protected]<0:0>(){0§<kotlin.Comparable<0:0>>}[0]
final inline fun <#A: kotlin/Comparable<#A>> (kotlin.collections/Iterable<#A>).com.huanshankeji.collections/isSortedDescending(): kotlin/Boolean // com.huanshankeji.collections/isSortedDescending|[email protected]<0:0>(){0§<kotlin.Comparable<0:0>>}[0]
final inline fun <#A: kotlin/Comparable<#A>> (kotlin.sequences/Sequence<#A>).com.huanshankeji.sequences/isSorted(): kotlin/Boolean // com.huanshankeji.sequences/isSorted|[email protected]<0:0>(){0§<kotlin.Comparable<0:0>>}[0]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.huanshankeji

@RequiresOptIn("This API is experimental. It may be changed in the future without notice.", RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
annotation class ExperimentalApi
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.huanshankeji

@ExperimentalApi
fun functionImplementationRemoved(): Nothing =
throw NotImplementedError("This function's implementation has been removed and the function will be removed too in the future.")
16 changes: 10 additions & 6 deletions core/src/commonMain/kotlin/com/huanshankeji/kotlin/Use.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.huanshankeji.kotlin

import com.huanshankeji.ExperimentalApi
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

// copied and adapted from https://github.com/JetBrains/kotlin/blob/e747a5a9a6070fd2ee0b2fd1fda1de3230c8307f/libraries/stdlib/jvm/src/kotlin/AutoCloseableJVM.kt#L23

/**
* Copied and adapted from [kotlin.use].
*/
@Deprecated("See https://kotlinlang.org/docs/whatsnew20.html#stable-autocloseable-interface")
//@Deprecated("See https://kotlinlang.org/docs/whatsnew20.html#stable-autocloseable-interface")
@ExperimentalApi
@OptIn(ExperimentalContracts::class)
inline fun <T, R> T.use(block: (T) -> R, close: T.() -> Unit): R {
contract {
Expand All @@ -27,15 +31,15 @@ inline fun <T, R> T.use(block: (T) -> R, close: T.() -> Unit): R {
/**
* Copied and adapted from [kotlin.closeFinally].
*/
@Deprecated("See https://kotlinlang.org/docs/whatsnew20.html#stable-autocloseable-interface")
/*private*/ inline fun <T> T.closeFinally(cause: Throwable?, close: T.() -> Unit) = when {
this == null -> {
}
//@Deprecated("See https://kotlinlang.org/docs/whatsnew20.html#stable-autocloseable-interface")
@PublishedApi
internal inline fun <T> T.closeFinally(cause: Throwable?, close: T.() -> Unit) = when {
this == null -> {}
cause == null -> close()
else ->
try {
close()
} catch (closeException: Throwable) {
cause.addSuppressed(closeException)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.huanshankeji.kotlin.function.parametertypeparameter

import com.huanshankeji.ExperimentalApi

private typealias NullableUnitReturnTypeParameterFunction<T> = ((T) -> Unit)?

@ExperimentalApi
inline operator fun <T> NullableUnitReturnTypeParameterFunction<T>.plus(noinline other: NullableUnitReturnTypeParameterFunction<T>): NullableUnitReturnTypeParameterFunction<T> =
if (this === null)
other
else if (other === null)
this
else {
{
this@plus(it)
other(it)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.huanshankeji.kotlin.function.receivertypeparameter

import com.huanshankeji.ExperimentalApi

private typealias NullableUnitReturnTypeReceiverFunction<T> = (T.() -> Unit)?

@ExperimentalApi
inline operator fun <T> NullableUnitReturnTypeReceiverFunction<T>.plus(noinline other: NullableUnitReturnTypeReceiverFunction<T>): NullableUnitReturnTypeReceiverFunction<T> =
if (this === null)
other
else if (other === null)
this
else {
{
this@plus()
other()
}
}
4 changes: 4 additions & 0 deletions core/src/jvmMain/kotlin/com/huanshankeji/jdbc/JdbcUrls.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.huanshankeji.jdbc

fun jdbcUrl(rdbms: String, host: String, port: Int?, database: String) =
"jdbc:$rdbms://$host${port?.let { ":$it" } ?: ""}/$database"
8 changes: 8 additions & 0 deletions coroutines/api/kotlin-common-coroutines.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ public final class com/huanshankeji/kotlinx/coroutine/AwaitKt {
public static final fun joinAny ([Lkotlinx/coroutines/Job;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class com/huanshankeji/kotlinx/coroutine/CoroutineAutoCloseable {
public abstract fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/huanshankeji/kotlinx/coroutine/CoroutineAutoCloseableKt {
public static final fun use (Lcom/huanshankeji/kotlinx/coroutine/CoroutineAutoCloseable;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class com/huanshankeji/kotlinx/coroutine/WithCoroutineScope {
public abstract fun getCoroutineScope ()Lkotlinx/coroutines/CoroutineScope;
}
Expand Down
5 changes: 5 additions & 0 deletions coroutines/api/kotlin-common-coroutines.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
// - Show declarations: true

// Library unique name: <com.huanshankeji:kotlin-common-coroutines>
abstract fun interface com.huanshankeji.kotlinx.coroutine/CoroutineAutoCloseable { // com.huanshankeji.kotlinx.coroutine/CoroutineAutoCloseable|null[0]
abstract suspend fun close() // com.huanshankeji.kotlinx.coroutine/CoroutineAutoCloseable.close|close(){}[0]
}

abstract interface com.huanshankeji.kotlinx.coroutine/WithCoroutineScope { // com.huanshankeji.kotlinx.coroutine/WithCoroutineScope|null[0]
abstract val coroutineScope // com.huanshankeji.kotlinx.coroutine/WithCoroutineScope.coroutineScope|{}coroutineScope[0]
abstract fun <get-coroutineScope>(): kotlinx.coroutines/CoroutineScope // com.huanshankeji.kotlinx.coroutine/WithCoroutineScope.coroutineScope.<get-coroutineScope>|<get-coroutineScope>(){}[0]
Expand All @@ -16,3 +20,4 @@ final suspend fun <#A: kotlin/Any?> (kotlin.collections/Collection<kotlinx.corou
final suspend fun <#A: kotlin/Any?> (kotlin.collections/Collection<kotlinx.coroutines/Deferred<#A>>).com.huanshankeji.kotlinx.coroutine/awaitAnyAndCancelOthers(): #A // com.huanshankeji.kotlinx.coroutine/awaitAnyAndCancelOthers|[email protected]<kotlinx.coroutines.Deferred<0:0>>(){0§<kotlin.Any?>}[0]
final suspend fun <#A: kotlin/Any?> com.huanshankeji.kotlinx.coroutine/awaitAny(kotlin/Array<out kotlinx.coroutines/Deferred<#A>>...): #A // com.huanshankeji.kotlinx.coroutine/awaitAny|awaitAny(kotlin.Array<out|kotlinx.coroutines.Deferred<0:0>>...){0§<kotlin.Any?>}[0]
final suspend fun com.huanshankeji.kotlinx.coroutine/joinAny(kotlin/Array<out kotlinx.coroutines/Job>...) // com.huanshankeji.kotlinx.coroutine/joinAny|joinAny(kotlin.Array<out|kotlinx.coroutines.Job>...){}[0]
final suspend inline fun <#A: com.huanshankeji.kotlinx.coroutine/CoroutineAutoCloseable?, #B: kotlin/Any?> (#A).com.huanshankeji.kotlinx.coroutine/use(kotlin/Function1<#A, #B>): #B // com.huanshankeji.kotlinx.coroutine/use|use@0:0(kotlin.Function1<0:0,0:1>){0§<com.huanshankeji.kotlinx.coroutine.CoroutineAutoCloseable?>;1§<kotlin.Any?>}[0]
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.huanshankeji.kotlinx.coroutine

import com.huanshankeji.ExperimentalApi
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.selects.select

@ExperimentalApi
suspend fun <T> awaitAny(vararg deferreds: Deferred<T>): T {
require(deferreds.isNotEmpty())
return select { deferreds.forEach { it.onAwait { it } } }
}

@ExperimentalApi
suspend fun <T> Collection<Deferred<T>>.awaitAny(): T {
require(isNotEmpty())
return select { forEach { it.onAwait { it } } }
}

@ExperimentalApi
suspend fun <T> Collection<Deferred<T>>.awaitAnyAndCancelOthers(): T {
require(isNotEmpty())
val firstAwaited = select { forEachIndexed { index, deferred -> deferred.onAwait { IndexedValue(index, it) } } }
Expand All @@ -22,11 +26,13 @@ suspend fun <T> Collection<Deferred<T>>.awaitAnyAndCancelOthers(): T {
return firstAwaited.value
}

@ExperimentalApi
suspend fun joinAny(vararg jobs: Job) {
require(jobs.isNotEmpty())
select { jobs.forEach { it.onJoin { } } }
}

@ExperimentalApi
suspend fun Collection<Job>.joinAny() {
require(isNotEmpty())
select { forEach { it.onJoin { } } }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.huanshankeji.kotlinx.coroutine

import com.huanshankeji.ExperimentalApi
import com.huanshankeji.kotlin.use

/**
* @see AutoCloseable
* Also see https://github.com/Kotlin/kotlinx.coroutines/issues/1191.
* Made a functional interface so that there is no need to add a function like the [AutoCloseable] one.
*/
@ExperimentalApi
fun interface CoroutineAutoCloseable {
suspend fun close()
}

suspend inline fun <T : CoroutineAutoCloseable?, R> T.use(block: (T) -> R): R =
use(block) { this?.close() }
Loading

0 comments on commit 0c919c1

Please sign in to comment.