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

ru.hnau.jutils.producer.container.DeferredPossibleContainer.kt Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
package ru.hnau.jutils.producer.container

import kotlinx.coroutines.Deferred
import ru.hnau.jutils.TimeValue
import ru.hnau.jutils.coroutines.deferred.resultOrNull
import ru.hnau.jutils.ifNull
import ru.hnau.jutils.possible.Possible
import ru.hnau.jutils.producer.Producer

@Deprecated("Use SuspendCachedGetter")
abstract class DeferredPossibleContainer(
        private val dataLifetime: TimeValue? = null
) : Producer>>() {

    companion object {

        fun  create(
                dataLifetime: TimeValue? = null,
                getter: () -> Deferred>
        ) = object : DeferredPossibleContainer(dataLifetime) {
            override fun getNewDeferredPossible() = getter.invoke()
        }

    }

    private var isObserving = false

    private var cachedDeferredPossibleSetTime = TimeValue.ZERO
    private var cachedDeferredPossible: Deferred>? = null
        set(value) {
            field?.cancel()
            field = value
        }

    private val isActualByLifetime: Boolean
        get() = dataLifetime == null || TimeValue.now() <= cachedDeferredPossibleSetTime + dataLifetime

    val existence: Deferred>?
        get() = synchronized(this) { cachedDeferredPossible?.takeIf { isActualByLifetime } }

    suspend fun await() = get().await()

    fun get(): Deferred> = synchronized(this) {
        var deferred = existence
        if (deferred == null) {
            deferred = getNewDeferredPossible()
            cachedDeferredPossible = deferred
            cachedDeferredPossibleSetTime = TimeValue.now()
            deferred.invokeOnCompletion {
                deferred.resultOrNull?.data.ifNull {
                    cachedDeferredPossible = null
                }
            }
        }
        deferred
    }

    override fun onAttached(listener: (Deferred>) -> Unit) {
        super.onAttached(listener)

        synchronized(this) {
            val existenceValue = existence
            if (existenceValue != null) {
                listener.invoke(existenceValue)
            } else {
                invalidate()
            }
        }

    }


    fun invalidate() = synchronized(this) {
        cachedDeferredPossible = null
        if (isObserving) {
            val newValue = get()
            call(newValue)
        }
    }

    override fun onIsObservingChanged(isObserving: Boolean) {
        super.onIsObservingChanged(isObserving)
        this.isObserving = isObserving
    }

    protected abstract fun getNewDeferredPossible(): Deferred>

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy