From bfdb200cc7a48e3410ac80885eab181daf539617 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Mon, 15 Jun 2015 22:57:41 +0300 Subject: [PATCH] Lazy: Use UNINITIALIZED_VALUE instead of null to indicate that value was not initialized. Remove escape and unescape methods. --- libraries/stdlib/src/kotlin/util/Lazy.kt | 43 ++++++++------------- libraries/stdlib/src/kotlin/util/LazyJVM.kt | 23 ++++++++--- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/libraries/stdlib/src/kotlin/util/Lazy.kt b/libraries/stdlib/src/kotlin/util/Lazy.kt index 585c0c2bcd1..3ed0b371e1f 100644 --- a/libraries/stdlib/src/kotlin/util/Lazy.kt +++ b/libraries/stdlib/src/kotlin/util/Lazy.kt @@ -38,45 +38,36 @@ public enum class LazyThreadSafetyMode { } -private object NULL_VALUE {} +private object UNINITIALIZED_VALUE -private fun escape(value: Any?): Any { - return value ?: NULL_VALUE -} - -private fun unescape(value: Any?): Any? { - return if (value === NULL_VALUE) null else value -} - - -private class LazyImpl(initializer: () -> T, private val lockObj: Any) : Lazy { +private class LazyImpl(initializer: () -> T) : Lazy { private var initializer: (() -> T)? = initializer - private volatile var _value: Any? = null + private volatile var _value: Any? = UNINITIALIZED_VALUE public override val value: T get() { val _v1 = _value - if (_v1 != null) { - return unescape(_v1) as T + if (_v1 !== UNINITIALIZED_VALUE) { + return _v1 as T } - return synchronized(lockObj) { + return synchronized(this) { val _v2 = _value - if (_v2 != null) { - unescape(_v2) as T + if (_v2 !== UNINITIALIZED_VALUE) { + _v2 as T } else { val typedValue = initializer!!() - _value = escape(typedValue) + _value = typedValue initializer = null typedValue } } } - override val valueCreated: Boolean = _value == null + override val valueCreated: Boolean = _value !== UNINITIALIZED_VALUE - override fun toString(): String = if (valueCreated) value.toString() else "Lazy value not created yet." + override fun toString(): String = if (valueCreated) value.toString() else "Lazy value not initialized yet." } @@ -84,18 +75,18 @@ private class UnsafeLazyImpl(initializer: () -> T) : Lazy { private var initializer: (() -> T)? = initializer - private var _value: Any? = null + private var _value: Any? = UNINITIALIZED_VALUE override val value: T get() { - if (_value == null) { - _value = escape(initializer!!()) + if (_value === UNINITIALIZED_VALUE) { + _value = initializer!!() initializer == null } - return unescape(_value) as T + return _value as T } - override val valueCreated: Boolean = _value == null + override val valueCreated: Boolean = _value !== UNINITIALIZED_VALUE - override fun toString(): String = if (valueCreated) value.toString() else "Lazy value not created yet." + override fun toString(): String = if (valueCreated) value.toString() else "Lazy value not initialized yet." } diff --git a/libraries/stdlib/src/kotlin/util/LazyJVM.kt b/libraries/stdlib/src/kotlin/util/LazyJVM.kt index b6f23a7815d..e49a5d299ec 100644 --- a/libraries/stdlib/src/kotlin/util/LazyJVM.kt +++ b/libraries/stdlib/src/kotlin/util/LazyJVM.kt @@ -1,14 +1,25 @@ package kotlin -/** Initializes a new instance of the [Lazy] that uses the specified initialization function [initializer] - * and the default thread-safety [LazyThreadSafetyMode.SYNCHRONIZED]. */ -public fun lazy(initializer: () -> T): Lazy = LazyImpl(initializer, Any()) +/** + * Initializes a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. + * + * 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 = LazyImpl(initializer) -/** Initializes a new instance of the [Lazy] that uses the specified initialization function [initializer] - * and thread-safety [mode]. */ +/** + * Initializes a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and thread-safety [mode]. + * + * 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 -> LazyImpl(initializer, Any()) + LazyThreadSafetyMode.SYNCHRONIZED -> LazyImpl(initializer) LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer) }