From 1145cc0d1b0aa2ea946704d44a7fcf02b55a6210 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 25 Sep 2015 19:13:12 +0300 Subject: [PATCH] Lazy: changes and clarifications after code-review. LazyThreadSafety.NONE is actually *NONE* now. --- libraries/stdlib/src/kotlin/util/Lazy.kt | 3 ++- libraries/stdlib/src/kotlin/util/LazyJVM.kt | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/stdlib/src/kotlin/util/Lazy.kt b/libraries/stdlib/src/kotlin/util/Lazy.kt index 32875bc0aa8..d436764021e 100644 --- a/libraries/stdlib/src/kotlin/util/Lazy.kt +++ b/libraries/stdlib/src/kotlin/util/Lazy.kt @@ -63,6 +63,7 @@ private object UNINITIALIZED_VALUE internal class SynchronizedLazyImpl(initializer: () -> T, lock: Any? = null) : Lazy(), Serializable { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE + // final field is required to enable safe publication of constructed instance private val lock = lock ?: this override val value: T @@ -101,7 +102,7 @@ internal class UnsafeLazyImpl(initializer: () -> T) : Lazy(), Serializ get() { if (_value === UNINITIALIZED_VALUE) { _value = initializer!!() - initializer == null + initializer = null } return _value as T } diff --git a/libraries/stdlib/src/kotlin/util/LazyJVM.kt b/libraries/stdlib/src/kotlin/util/LazyJVM.kt index e6a07c64efb..570d509a758 100644 --- a/libraries/stdlib/src/kotlin/util/LazyJVM.kt +++ b/libraries/stdlib/src/kotlin/util/LazyJVM.kt @@ -51,14 +51,19 @@ public fun lazy(lock: Any?, initializer: () -> T): Lazy = SynchronizedLazy private class SafePublicationLazyImpl(initializer: () -> T) : Lazy(), Serializable { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE + // this final field is required to enable safe publication of constructed instance 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 + val initializerValue = initializer + // if we see null in initializer here, it means that the value is already set by another thread + if (initializerValue != null) { + val newValue = initializerValue() + if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, newValue)) { + initializer = null + } } } return _value as T