Add manual invalidation to counter lazies

This commit is contained in:
DBotThePony 2023-08-17 22:55:44 +07:00
parent e6758f1e27
commit 2e4984162b
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 35 additions and 9 deletions

View File

@ -7,7 +7,7 @@ import java.util.function.IntSupplier
/** /**
* If synchronization is not required, [CounterInvalidatedLazy] should be used instead. * If synchronization is not required, [CounterInvalidatedLazy] should be used instead.
*/ */
class AtomicallyInvalidatedLazy<V>(private val invalidator: IntSupplier, private val initializer: () -> V) : Lazy<V> { class AtomicallyInvalidatedLazy<V>(private val invalidator: IntSupplier, private val initializer: () -> V) : InvalidableLazy<V> {
constructor(invalidator: AtomicInteger, initializer: () -> V) : this(invalidator::get, initializer) constructor(invalidator: AtomicInteger, initializer: () -> V) : this(invalidator::get, initializer)
@Volatile @Volatile
@ -18,10 +18,7 @@ class AtomicallyInvalidatedLazy<V>(private val invalidator: IntSupplier, private
override val value: V get() { override val value: V get() {
if (thisCounter != invalidator.asInt) { if (thisCounter != invalidator.asInt) {
lock.lock() invalidate()
this.stored = Companion
thisCounter = invalidator.asInt
lock.unlock()
} }
var stored = stored var stored = stored
@ -40,6 +37,13 @@ class AtomicallyInvalidatedLazy<V>(private val invalidator: IntSupplier, private
} }
} }
override fun invalidate() {
lock.lock()
this.stored = Companion
thisCounter = invalidator.asInt
lock.unlock()
}
override fun isInitialized(): Boolean { override fun isInitialized(): Boolean {
return stored !== Companion && thisCounter == invalidator.asInt return stored !== Companion && thisCounter == invalidator.asInt
} }

View File

@ -7,9 +7,9 @@ import java.util.function.IntSupplier
/** /**
* This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined * This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined
* *
* For synchronized use case, [AtomicallyInvalidatedLazy] should be used * For thread synchronized use case, [AtomicallyInvalidatedLazy] should be used
*/ */
fun <V> countingLazy(invalidator: IntSupplier, initializer: () -> V): Lazy<V> { fun <V> countingLazy(invalidator: IntSupplier, initializer: () -> V): InvalidableLazy<V> {
if (invalidator is IntCounter) { if (invalidator is IntCounter) {
return SmartCounterInvalidatedLazy(invalidator, initializer) return SmartCounterInvalidatedLazy(invalidator, initializer)
} }
@ -17,12 +17,21 @@ fun <V> countingLazy(invalidator: IntSupplier, initializer: () -> V): Lazy<V> {
return CounterInvalidatedLazy(invalidator, initializer) return CounterInvalidatedLazy(invalidator, initializer)
} }
/**
* This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined
*
* For thread synchronized use case, [AtomicallyInvalidatedLazy] should be used
*/
fun <V> countingLazy(invalidator: AtomicInteger, initializer: () -> V): InvalidableLazy<V> {
return CounterInvalidatedLazy(invalidator, initializer)
}
/** /**
* This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined * This lazy is not synchronized, so in event of two or more threads accessing value behavior of this implementation is undefined
* *
* For synchronized use case, [AtomicallyInvalidatedLazy] should be used * For synchronized use case, [AtomicallyInvalidatedLazy] should be used
*/ */
class CounterInvalidatedLazy<V>(private val invalidator: IntSupplier, private val initializer: () -> V) : Lazy<V> { class CounterInvalidatedLazy<V>(private val invalidator: IntSupplier, private val initializer: () -> V) : InvalidableLazy<V> {
constructor(invalidator: AtomicInteger, initializer: () -> V) : this(invalidator::get, initializer) constructor(invalidator: AtomicInteger, initializer: () -> V) : this(invalidator::get, initializer)
private var thisCounter = -1 private var thisCounter = -1
@ -44,6 +53,10 @@ class CounterInvalidatedLazy<V>(private val invalidator: IntSupplier, private va
return stored !== Companion && thisCounter == invalidator.asInt return stored !== Companion && thisCounter == invalidator.asInt
} }
override fun invalidate() {
this.stored = Companion
}
private companion object private companion object
} }
@ -52,7 +65,7 @@ class CounterInvalidatedLazy<V>(private val invalidator: IntSupplier, private va
* *
* For synchronized use case, [AtomicallyInvalidatedLazy] should be used * For synchronized use case, [AtomicallyInvalidatedLazy] should be used
*/ */
class SmartCounterInvalidatedLazy<V>(invalidator: IntCounter, private val initializer: () -> V) : Lazy<V> { class SmartCounterInvalidatedLazy<V>(invalidator: IntCounter, private val initializer: () -> V) : InvalidableLazy<V> {
init { init {
invalidator.addListener(IntConsumer { invalidator.addListener(IntConsumer {
stored = Companion stored = Companion
@ -72,6 +85,10 @@ class SmartCounterInvalidatedLazy<V>(invalidator: IntCounter, private val initia
return stored return stored
} }
override fun invalidate() {
this.stored = Companion
}
override fun isInitialized(): Boolean { override fun isInitialized(): Boolean {
return stored !== Companion return stored !== Companion
} }

View File

@ -0,0 +1,5 @@
package ru.dbotthepony.mc.otm.core.util
interface InvalidableLazy<V> : Lazy<V> {
fun invalidate()
}