From 3915cfcea631d2a225bd5627eb067ac32738b355 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 25 Sep 2015 21:59:37 +0300 Subject: [PATCH] Merge Lazy's declarations in one file. --- libraries/stdlib/src/kotlin/util/Lazy.kt | 84 ++++++++++++++++++++- libraries/stdlib/src/kotlin/util/LazyJVM.kt | 84 --------------------- 2 files changed, 82 insertions(+), 86 deletions(-) delete mode 100644 libraries/stdlib/src/kotlin/util/LazyJVM.kt diff --git a/libraries/stdlib/src/kotlin/util/Lazy.kt b/libraries/stdlib/src/kotlin/util/Lazy.kt index d436764021e..d4fe98c1dbe 100644 --- a/libraries/stdlib/src/kotlin/util/Lazy.kt +++ b/libraries/stdlib/src/kotlin/util/Lazy.kt @@ -1,4 +1,3 @@ -@file:kotlin.jvm.JvmMultifileClass @file:kotlin.jvm.JvmName("LazyKt") package kotlin @@ -25,6 +24,50 @@ public abstract class Lazy internal constructor() { */ public fun lazyOf(value: T): Lazy = InitializedLazyImpl(value) +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. + * + * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. + * + * 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. + */ +@kotlin.jvm.JvmVersion +public fun lazy(initializer: () -> T): Lazy = SynchronizedLazyImpl(initializer) + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and thread-safety [mode]. + * + * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. + * + * Note that when the [LazyThreadSafetyMode.SYNCHRONIZED] mode is specified 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. + */ +@kotlin.jvm.JvmVersion +public fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = + when (mode) { + LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer) + LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer) + LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer) + } + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. + * + * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. + * + * The returned instance uses the specified [lock] object to synchronize on. + * When the [lock] is not specified the instance uses itself to synchronize on, + * 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. + */ +@kotlin.jvm.JvmVersion +public fun lazy(lock: Any?, initializer: () -> T): Lazy = SynchronizedLazyImpl(initializer, lock) + /** * An extension to delegate a read-only property of type [T] to an instance of [Lazy]. * @@ -60,7 +103,7 @@ public enum class LazyThreadSafetyMode { private object UNINITIALIZED_VALUE -internal class SynchronizedLazyImpl(initializer: () -> T, lock: Any? = null) : Lazy(), Serializable { +private 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 @@ -94,6 +137,7 @@ internal class SynchronizedLazyImpl(initializer: () -> T, lock: Any? = nu private fun writeReplace(): Any = InitializedLazyImpl(value) } +// internal to be called from lazy in JS internal class UnsafeLazyImpl(initializer: () -> T) : Lazy(), Serializable { private var initializer: (() -> T)? = initializer private var _value: Any? = UNINITIALIZED_VALUE @@ -121,3 +165,39 @@ private class InitializedLazyImpl(override val value: T) : Lazy(), Ser override fun toString(): String = value.toString() } + +@kotlin.jvm.JvmVersion +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 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 + } + + 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") + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/util/LazyJVM.kt b/libraries/stdlib/src/kotlin/util/LazyJVM.kt deleted file mode 100644 index 570d509a758..00000000000 --- a/libraries/stdlib/src/kotlin/util/LazyJVM.kt +++ /dev/null @@ -1,84 +0,0 @@ -@file:kotlin.jvm.JvmMultifileClass -@file:kotlin.jvm.JvmName("LazyKt") - -package kotlin - -import java.io.Serializable - - -/** - * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] - * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. - * - * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. - * - * 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. - */ -public fun lazy(initializer: () -> T): Lazy = SynchronizedLazyImpl(initializer) - -/** - * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] - * and thread-safety [mode]. - * - * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. - * - * Note that when the [LazyThreadSafetyMode.SYNCHRONIZED] mode is specified 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. - */ -public fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = - when (mode) { - LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer) - LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer) - LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer) - } - -/** - * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] - * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. - * - * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. - * - * The returned instance uses the specified [lock] object to synchronize on. - * When the [lock] is not specified the instance uses itself to synchronize on, - * 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. - */ -public fun lazy(lock: Any?, initializer: () -> T): Lazy = SynchronizedLazyImpl(initializer, lock) - - -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 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 - } - - 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") - } -} \ No newline at end of file