All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.jetbrains.datalore.base.async.PlatformAsyncs.kt Maven / Gradle / Ivy

There is a newer version: 4.5.3-alpha1
Show newest version
/*
 * 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