fuookami.ospf.kotlin.utils.meta_programming.LazyDelegate.kt Maven / Gradle / Ivy
package fuookami.ospf.kotlin.utils.meta_programming
import java.util.concurrent.atomic.*
import kotlin.reflect.*
import kotlinx.coroutines.*
fun lazyDelegate(lazyFunc: () -> U): LazyDelegate {
return LazyDelegate(lazyFunc)
}
@JvmName("selfLazyDelegate")
fun lazyDelegate(lazyFunc: (T) -> U): SelfLazyDelegate {
return SelfLazyDelegate(lazyFunc)
}
fun lazyDelegate(lazyKProperty: KProperty1): SelfLazyDelegate {
return SelfLazyDelegate { lazyKProperty(it) }
}
fun suspendLazy(lazyFunc: suspend () -> T): SuspendLazy {
return SuspendLazy(lazyFunc)
}
class LazyDelegate(
private val lazyFunc: () -> U
) {
lateinit var range: U
operator fun getValue(self: T, property: KProperty<*>): U {
if (!::range.isInitialized) {
range = lazyFunc()
}
return range
}
operator fun setValue(self: T, property: KProperty<*>, value: U) {
if (!::range.isInitialized) {
range = lazyFunc()
}
range = value
}
}
class SelfLazyDelegate(
private val lazyFunc: (T) -> U
) {
lateinit var range: U
operator fun getValue(self: T, property: KProperty<*>): U {
if (!::range.isInitialized) {
range = lazyFunc(self)
}
return range
}
operator fun setValue(self: T, property: KProperty<*>, value: U) {
if (!::range.isInitialized) {
range = lazyFunc(self)
}
range = value
}
}
class SuspendLazy(
private val lazyFunc: suspend () -> T,
) {
private val value = AtomicReference>()
suspend operator fun invoke(): T = (
value.get()
?: coroutineScope {
value.updateAndGet { actual ->
actual ?: async { lazyFunc() }
}
}
).await()
}