Provide LazyThreadSafetyMode.PUBLICATION: concurrent non-blocking initializations, single publication.
This commit is contained in:
@@ -43,6 +43,12 @@ public enum class LazyThreadSafetyMode {
|
||||
*/
|
||||
SYNCHRONIZED,
|
||||
|
||||
/**
|
||||
* Initializer function can be called several times on concurrent access to uninitialized [Lazy] instance value,
|
||||
* but only first returned value will be used as the value of [Lazy] instance.
|
||||
*/
|
||||
PUBLICATION,
|
||||
|
||||
/**
|
||||
* No locks are used to synchronize the access to the [Lazy] instance value; if the instance is accessed from multiple threads, its behavior is undefined.
|
||||
*
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
package kotlin
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
|
||||
@@ -28,6 +30,7 @@ public fun lazy<T>(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initial
|
||||
public fun lazy<T>(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
when (mode) {
|
||||
LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
|
||||
LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
|
||||
LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
|
||||
}
|
||||
|
||||
@@ -43,3 +46,34 @@ public fun lazy<T>(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
* Also this behavior can be changed in the future.
|
||||
*/
|
||||
public fun lazy<T>(lock: Any?, initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer, lock)
|
||||
|
||||
|
||||
private class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
|
||||
private var initializer: (() -> T)? = initializer
|
||||
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
|
||||
private val final: Any = UNINITIALIZED_VALUE
|
||||
|
||||
override val value: T
|
||||
get() {
|
||||
if (_value === UNINITIALIZED_VALUE) {
|
||||
val newValue = initializer!!()
|
||||
if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, newValue)) {
|
||||
initializer == null
|
||||
}
|
||||
}
|
||||
return _value as T
|
||||
}
|
||||
|
||||
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
|
||||
|
||||
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
|
||||
|
||||
private fun writeReplace(): Any = InitializedLazyImpl(value)
|
||||
|
||||
companion object {
|
||||
private val valueUpdater = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(
|
||||
SafePublicationLazyImpl::class.java,
|
||||
Any::class.java,
|
||||
"_value")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user