commonMain.jetbrains.datalore.base.async.Asyncs.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lets-plot-common Show documentation
Show all versions of lets-plot-common Show documentation
Lets-Plot JVM package without rendering part
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.base.async
import jetbrains.datalore.base.function.Consumer
import jetbrains.datalore.base.function.Runnable
import jetbrains.datalore.base.function.Supplier
import jetbrains.datalore.base.function.Value
import jetbrains.datalore.base.registration.Registration
object Asyncs {
fun isFinished(async: Async<*>): Boolean {
val finished = Value(false)
async.onResult(
{ finished.set(true) },
{ finished.set(true) }
).remove()
return finished.get()
}
fun constant(value: ValueT): Async {
return object : Async {
override fun onSuccess(successHandler: Consumer): Registration {
successHandler(value)
return Registration.EMPTY
}
override fun onResult(successHandler: Consumer, failureHandler: Consumer): Registration {
return onSuccess(successHandler)
}
override fun onFailure(failureHandler: Consumer): Registration {
return Registration.EMPTY
}
override fun map(success: (ValueT) -> ResultT): Async {
val result: ResultT
try {
result = success(value)
} catch (t: Throwable) {
return failure(t)
}
//return cannot be moved to try block to avoid catching possible errors from Asyncs.constant call
return constant(result)
}
override fun flatMap(success: (ValueT) -> Async?): Async {
val result: Async?
try {
result = success(value)
} catch (t: Throwable) {
return failure(t)
}
//return cannot be moved to try block to avoid catching possible errors from Asyncs.constant call
return if (result == null) {
constant(null)
} else {
@Suppress("UNCHECKED_CAST")
result as Async
}
}
}
}
fun failure(t: Throwable): Async {
return object : Async {
override fun onSuccess(successHandler: Consumer): Registration {
return Registration.EMPTY
}
override fun onResult(successHandler: Consumer, failureHandler: Consumer): Registration {
return onFailure(failureHandler)
}
override fun onFailure(failureHandler: Consumer): Registration {
failureHandler(t)
return Registration.EMPTY
}
override fun map(success: (ValueT) -> ResultT): Async {
return failure(t)
}
override fun flatMap(success: (ValueT) -> Async?): Async {
return failure(t)
}
}
}
fun voidAsync(): Async {
return constant(Unit)
}
fun toUnit(async: Async): Async {
return map(async, {}, ThreadSafeAsync())
}
internal fun map(
async: Async,
f: (SourceT) -> TargetT,
resultAsync: ResolvableAsync):
Async {
async.onResult(
{ value ->
val result: TargetT
try {
result = f(value)
} catch (e: Exception) {
resultAsync.failure(e)
return@onResult
}
resultAsync.success(result)
},
{ value -> resultAsync.failure(value) })
return resultAsync
}
internal fun select(
async: Async,
f: (SourceT) -> Async?,
resultAsync: ResolvableAsync):
Async {
async.onResult(
{ value ->
val async1: Async?
try {
async1 = f(value)
} catch (e: Exception) {
resultAsync.failure(e)
return@onResult
}
if (async1 == null) {
resultAsync.success(null)
} else {
delegate(async1, resultAsync)
}
},
{ value -> resultAsync.failure(value) })
return resultAsync
}
fun seq(first: Async, second: Async): Async {
return select(first, { second }, ThreadSafeAsync())
}
fun onAnyResult(async: Async<*>, r: Runnable): Registration {
return async.onResult({ r.run() }, { r.run() })
}
fun untilSuccess(s: Supplier>): Async {
val result = SimpleAsync()
val async: Async
val successConsumer: Consumer = { value -> result.success(value) }
try {
async = s.get()
} catch (ignore: Exception) {
untilSuccess(s).onSuccess(successConsumer)
return result
}
async.onResult(successConsumer, { untilSuccess(s).onSuccess(successConsumer) })
return result
}
internal fun delegate(from: Async, to: AsyncResolver): Registration {
return from.onResult({ value -> to.success(value) }, { value -> to.failure(value) })
}
fun pair(first: Async, second: Async): Async> {
val res = SimpleAsync>()
val proxy = SimpleAsync()
val firstPaired = PairedAsync(first)
val secondPaired = PairedAsync(second)
proxy.onResult(
{
if (firstPaired.mySucceeded && secondPaired.mySucceeded) {
@Suppress("UNCHECKED_CAST")
res.success(Pair(
firstPaired.myItem as FirstT,
secondPaired.myItem as SecondT))
} else {
res.failure(Throwable("internal error in pair async"))
}
},
{ throwable ->
res.failure(throwable)
})
firstPaired.pair(secondPaired, proxy)
secondPaired.pair(firstPaired, proxy)
return res
}
private class PairedAsync(private val myAsync: Async) {
internal var myItem: ItemT? = null
internal var mySucceeded: Boolean = false
private var myReg: Registration? = null
internal fun pair(anotherInfo: PairedAsync, async: SimpleAsync) {
if (async.hasSucceeded() || async.hasFailed()) {
return
}
myReg = myAsync.onResult(
{ item ->
myItem = item
mySucceeded = true
if (anotherInfo.mySucceeded) {
async.success(Unit)
}
},
{ failure ->
//reg == null can happen in case if myAsync fails instantly
if (anotherInfo.myReg != null) {
anotherInfo.myReg!!.remove()
}
async.failure(failure)
})
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy