Introduce final field in SynchronizedLazyImpl to enable safe publication.

This commit is contained in:
Ilya Gorbunov
2015-09-25 03:59:43 +03:00
parent 1986d8d7f8
commit 4a062698f2
2 changed files with 5 additions and 12 deletions
+2 -5
View File
@@ -54,11 +54,10 @@ public enum class LazyThreadSafetyMode {
private object UNINITIALIZED_VALUE private object UNINITIALIZED_VALUE
internal open class LazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable { internal class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>(), Serializable {
private var initializer: (() -> T)? = initializer private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE @Volatile private var _value: Any? = UNINITIALIZED_VALUE
protected open val lock: Any private val lock = lock ?: this
get() = this
override val value: T override val value: T
get() { get() {
@@ -88,8 +87,6 @@ internal open class LazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializa
private fun writeReplace(): Any = InitializedLazyImpl(value) private fun writeReplace(): Any = InitializedLazyImpl(value)
} }
internal class ExternallySynchronizedLazyImpl<out T>(override val lock: Any, initializer: () -> T): LazyImpl<T>(initializer)
internal class UnsafeLazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable { internal class UnsafeLazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
private var initializer: (() -> T)? = initializer private var initializer: (() -> T)? = initializer
private var _value: Any? = UNINITIALIZED_VALUE private var _value: Any? = UNINITIALIZED_VALUE
+3 -7
View File
@@ -13,7 +13,7 @@ package kotlin
* Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
* the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future. * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
*/ */
public fun lazy<T>(initializer: () -> T): Lazy<T> = LazyImpl(initializer) public fun lazy<T>(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
/** /**
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
@@ -27,7 +27,7 @@ public fun lazy<T>(initializer: () -> T): Lazy<T> = LazyImpl(initializer)
*/ */
public fun lazy<T>(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> = public fun lazy<T>(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
when (mode) { when (mode) {
LazyThreadSafetyMode.SYNCHRONIZED -> LazyImpl(initializer) LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer) LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
} }
@@ -42,8 +42,4 @@ public fun lazy<T>(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
* in this case do not synchronize from external code on the returned instance as it may cause accidental deadlock. * in this case do not synchronize from external code on the returned instance as it may cause accidental deadlock.
* Also this behavior can be changed in the future. * Also this behavior can be changed in the future.
*/ */
public fun lazy<T>(lock: Any?, initializer: () -> T): Lazy<T> = public fun lazy<T>(lock: Any?, initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer, lock)
if (lock != null)
ExternallySynchronizedLazyImpl(lock, initializer)
else
LazyImpl(initializer)