ru.hnau.jutils.producer.container.DeferredPossibleContainer.kt Maven / Gradle / Ivy
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>
}