commonMain.jetbrains.datalore.base.async.PlatformAsyncs.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.concurrent.AtomicInteger
import jetbrains.datalore.base.concurrent.Lock
import jetbrains.datalore.base.concurrent.execute
import jetbrains.datalore.base.gcommon.collect.TreeMap
object PlatformAsyncs {
fun parallel(vararg asyncs: Async<*>): Async {
return parallel(listOf(*asyncs))
}
fun parallelResult(asyncs: Collection>): Async> {
return runParallel(asyncs, true)
}
fun parallel(asyncs: Collection>, alwaysSucceed: Boolean = false): Async {
return Asyncs.toUnit(runParallel(asyncs, alwaysSucceed))
}
fun composite(asyncs: List>): Async> {
return runParallel(asyncs, false)
}
private fun runParallel(asyncs: Collection>,
alwaysSucceed: Boolean): Async> {
val result: ResolvableAsync> = ThreadSafeAsync()
val inProgress = AtomicInteger(asyncs.size)
val values = OrderedValues()
val exceptions = ThreadSafeThrowables()
val checkTermination = {
if (inProgress.decrementAndGet() <= 0) {
if (!exceptions.isEmpty && !alwaysSucceed) {
result.failure(exceptions.toSingleException())
} else {
result.success(values.get())
}
}
}
for ((i, async) in asyncs.withIndex()) {
async.onResult(
{ item ->
values[i] = item
checkTermination()
},
{ failure ->
exceptions.add(failure)
checkTermination()
})
}
if (asyncs.isEmpty()) {
checkTermination()
}
return result
}
private class OrderedValues {
private val myLock = Lock()
private val myMap = TreeMap()
internal operator fun set(index: Int, value: ValueT) {
myLock.execute {
myMap.put(index, value)
}
}
internal fun get(): List {
myLock.execute {
return ArrayList(myMap.values)
}
}
}
private class ThreadSafeThrowables {
private val myLock = Lock()
private val myThrowables = ArrayList(0)
internal val isEmpty: Boolean
get() = myLock.execute {
return myThrowables.isEmpty()
}
internal fun add(t: Throwable) {
myLock.execute {
myThrowables.add(t)
}
}
internal fun toSingleException(): Throwable {
myLock.execute {
check(!myThrowables.isEmpty()) { "Empty collection" }
return if (myThrowables.size == 1) {
myThrowables[0]
} else ThrowableCollectionException(ArrayList(myThrowables))
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy