Provide lazy implementation with an external object to synchronize on.
This commit is contained in:
@@ -30,7 +30,7 @@ public object Delegates {
|
||||
* the property delegate object itself is used as a lock.
|
||||
* @param initializer the function that returns the value of the property.
|
||||
*/
|
||||
deprecated("Use lazy {} instead in kotlin package")
|
||||
deprecated("Use lazy(lock) {} instead in kotlin package", ReplaceWith("lazy(lock, initializer)"))
|
||||
public fun blockingLazy<T>(lock: Any?, initializer: () -> T): ReadOnlyProperty<Any?, T> = BlockingLazyVal(lock, initializer)
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,9 +51,11 @@ public enum class LazyThreadSafetyMode {
|
||||
|
||||
private object UNINITIALIZED_VALUE
|
||||
|
||||
private class LazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
|
||||
private open class LazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
|
||||
private var initializer: (() -> T)? = initializer
|
||||
private volatile var _value: Any? = UNINITIALIZED_VALUE
|
||||
protected open val lock: Any
|
||||
get() = this
|
||||
|
||||
override val value: T
|
||||
get() {
|
||||
@@ -62,7 +64,7 @@ private class LazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
|
||||
return _v1 as T
|
||||
}
|
||||
|
||||
return synchronized(this) {
|
||||
return synchronized(lock) {
|
||||
val _v2 = _value
|
||||
if (_v2 !== UNINITIALIZED_VALUE) {
|
||||
_v2 as T
|
||||
@@ -83,6 +85,7 @@ private class LazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
|
||||
private fun writeReplace(): Any = InitializedLazyImpl(value)
|
||||
}
|
||||
|
||||
private class ExternallySynchronizedLazyImpl<out T>(override val lock: Any, initializer: () -> T): LazyImpl<T>(initializer)
|
||||
|
||||
private class UnsafeLazyImpl<out T>(initializer: () -> T) : Lazy<T>(), Serializable {
|
||||
private var initializer: (() -> T)? = initializer
|
||||
|
||||
@@ -27,3 +27,20 @@ public fun lazy<T>(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
LazyThreadSafetyMode.SYNCHRONIZED -> LazyImpl(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<T>(lock: Any?, initializer: () -> T): Lazy<T> =
|
||||
if (lock != null)
|
||||
ExternallySynchronizedLazyImpl(lock, initializer)
|
||||
else
|
||||
LazyImpl(initializer)
|
||||
Reference in New Issue
Block a user