Rewrite the AppDependencies system.

This commit is contained in:
Greyson Parrelli
2024-05-22 15:44:24 -04:00
committed by Cody Henthorne
parent a0131bf39b
commit b6a4e1f145
560 changed files with 2909 additions and 3036 deletions

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.core.util
import kotlin.reflect.KProperty
/**
* Identical to Kotlin's built-in [lazy] delegate, but with a `reset` method that allows the value to be reset to it's default state (and therefore recomputed
* upon next access).
*/
fun <T> resettableLazy(initializer: () -> T): ResettableLazy<T> {
return ResettableLazy(initializer)
}
/**
* @see resettableLazy
*/
class ResettableLazy<T>(
val initializer: () -> T
) {
// We need to distinguish between a lazy value of null and a lazy value that has not been initialized yet
@Volatile
private var value: Any? = UNINITIALIZED
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (value === UNINITIALIZED) {
synchronized(this) {
if (value === UNINITIALIZED) {
value = initializer()
}
}
}
@Suppress("UNCHECKED_CAST")
return value as T
}
fun reset() {
value = UNINITIALIZED
}
fun isInitialized(): Boolean {
return value !== UNINITIALIZED
}
override fun toString(): String {
return if (isInitialized()) {
value.toString()
} else {
"Lazy value not initialized yet."
}
}
companion object {
private val UNINITIALIZED = Any()
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.core.util
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertTrue
import org.junit.Test
import java.util.concurrent.CountDownLatch
class ResettableLazyTests {
@Test
fun `value only computed once`() {
var counter = 0
val lazy: Int by resettableLazy {
counter++
}
assertEquals(0, lazy)
assertEquals(0, lazy)
assertEquals(0, lazy)
}
@Test
fun `value recomputed after a reset`() {
var counter = 0
val _lazy = resettableLazy {
counter++
}
val lazy by _lazy
assertEquals(0, lazy)
_lazy.reset()
assertEquals(1, lazy)
_lazy.reset()
assertEquals(2, lazy)
}
@Test
fun `isInitialized - general`() {
val _lazy = resettableLazy { 1 }
val lazy: Int by _lazy
assertFalse(_lazy.isInitialized())
val x = lazy + 1
assertEquals(2, x)
assertTrue(_lazy.isInitialized())
_lazy.reset()
assertFalse(_lazy.isInitialized())
}
/**
* I've verified that without the synchronization inside of resettableLazy, this test usually fails.
*/
@Test
fun `ensure synchronization works`() {
val numRounds = 100
val numThreads = 5
for (i in 1..numRounds) {
var counter = 0
val lazy: Int by resettableLazy {
counter++
}
val latch = CountDownLatch(numThreads)
for (j in 1..numThreads) {
Thread {
val x = lazy + 1
latch.countDown()
}.start()
}
latch.await()
assertEquals(1, counter)
}
}
}