add RecursionPreventingSafePublicationLazy

This commit is contained in:
Daniil Ovchinnikov
2018-12-05 17:10:39 +03:00
parent 3e6ce37c72
commit 1d1b5f0ff9
2 changed files with 53 additions and 0 deletions
@@ -22,3 +22,5 @@ fun <E> Collection<E>.toArray(empty: Array<E>): Array<E> {
}
fun <T> lazyPub(initializer: () -> T): Lazy<T> = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
fun <T : Any> lazyPreventingRecursion(initializer: () -> T): Lazy<T?> = RecursionPreventingSafePublicationLazy(initializer)
@@ -0,0 +1,51 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util
import com.intellij.openapi.util.RecursionManager
import java.util.concurrent.atomic.AtomicReference
/**
* Same as [SafePublicationLazyImpl], but returns `null` in case of computation recursion occurred.
*/
class RecursionPreventingSafePublicationLazy<T : Any>(initializer: () -> T) : Lazy<T?> {
@Volatile
private var initializer: (() -> T)? = initializer
private val valueRef: AtomicReference<T> = AtomicReference()
override val value: T?
get() {
val computedValue = valueRef.get()
if (computedValue !== null) {
return computedValue
}
val initializerValue = initializer
if (initializerValue === null) {
// Some thread managed to clear the initializer => it managed to set the value.
return valueRef.get()
}
val newValue = ourRecursionGuard.doPreventingRecursion(this, false, initializerValue)
if (newValue === null) {
// In case of recursion don't update [_value] and don't clear [initializer].
return null
}
if (!valueRef.compareAndSet(null, newValue)) {
// Some thread managed to set the value.
return valueRef.get()
}
initializer = null
return newValue
}
override fun isInitialized(): Boolean = valueRef.get() !== null
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
companion object {
private val ourRecursionGuard = RecursionManager.createGuard("RecursionPreventingSafePublicationLazy")
}
}