package org.mariotaku.ktextension import nl.komponents.kovenant.Deferred import nl.komponents.kovenant.Promise import nl.komponents.kovenant.deferred import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicReferenceArray /** * Created by mariotaku on 2016/12/2. */ fun combine(promises: List>): Promise, E> { return concreteCombine(promises) } fun concreteCombine(promises: List>): Promise, E> { val deferred = deferred, E>() val results = AtomicReferenceArray(promises.size) val successCount = AtomicInteger(promises.size) fun createArray(): List { return (0 until results.length()).map { results[it] } } fun Promise.registerSuccess(idx: Int) { success { v -> results.set(idx, v) if (successCount.decrementAndGet() == 0) { deferred.resolve(createArray()) } } } fun Deferred.registerFail(promises: List>) { val failCount = AtomicInteger(0) promises.forEach { promise -> promise.fail { e -> if (failCount.incrementAndGet() == 1) { this.reject(e) } } } } promises.forEachIndexed { idx, promise -> promise.registerSuccess(idx) } deferred.registerFail(promises) return deferred.promise }