Merge "Minor cleanup of comments and formatting in snapshot code." into androidx-main
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index ed21806..7aeaea8 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -2571,7 +2571,7 @@
isComposing = true
try {
startRoot()
- // Ignore reads of derivedStatOf recalculations
+ // Ignore reads of derivedStateOf recalculations
observeDerivedStateRecalculations(
start = {
childrenComposing++
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt
index ffa0316..884040e 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt
@@ -15,6 +15,7 @@
*/
@file:OptIn(ExperimentalTypeInference::class)
+
package androidx.compose.runtime
import androidx.compose.runtime.external.kotlinx.collections.immutable.PersistentList
@@ -204,9 +205,11 @@
* The componentN() operators allow state objects to be used with the property destructuring
* syntax
*
+ * ```
* var (foo, setFoo) = remember { mutableStateOf(0) }
* setFoo(123) // set
* foo == 123 // get
+ * ```
*/
override operator fun component1(): T = value
@@ -330,12 +333,13 @@
SnapshotStateList<T>().also { it.addAll(elements.toList()) }
/**
- * Create an instance of MutableList<T> from a collection that is observable and can be snapshot.
+ * Create an instance of [MutableList]<T> from a collection that is observable and can be
+ * snapshot.
*/
fun <T> Collection<T>.toMutableStateList() = SnapshotStateList<T>().also { it.addAll(this) }
/**
- * Create a instance of MutableMap<K, V> that is observable and can be snapshot.
+ * Create a instance of [MutableMap]<K, V> that is observable and can be snapshot.
*
* @sample androidx.compose.runtime.samples.stateMapSample
*
@@ -347,7 +351,7 @@
fun <K, V> mutableStateMapOf() = SnapshotStateMap<K, V>()
/**
- * Create a instance of MutableMap<K, V> that is observable and can be snapshot.
+ * Create a instance of [MutableMap]<K, V> that is observable and can be snapshot.
*
* @see mutableStateOf
* @see mutableMapOf
@@ -358,7 +362,7 @@
SnapshotStateMap<K, V>().apply { putAll(pairs.toMap()) }
/**
- * Create an instance of MutableMap<K, V> from a collection of pairs that is observable and can be
+ * Create an instance of [MutableMap]<K, V> from a collection of pairs that is observable and can be
* snapshot.
*/
@Suppress("unused")
@@ -386,11 +390,14 @@
}
private typealias DerivedStateObservers = Pair<(DerivedState<*>) -> Unit, (DerivedState<*>) -> Unit>
+
private val derivedStateObservers = SnapshotThreadLocal<PersistentList<DerivedStateObservers>>()
+
private class DerivedSnapshotState<T>(
private val calculation: () -> T
) : StateObject, DerivedState<T> {
private var first: ResultRecord<T> = ResultRecord()
+
private class ResultRecord<T> : StateRecord() {
var dependencies: HashSet<StateObject>? = null
var result: T? = null
@@ -467,15 +474,16 @@
first = value as ResultRecord<T>
}
- override val value: T get() {
- // Unlike most state objects, the record list of a derived state can change during a read
- // because reading updates the cache. To account for this, instead of calling readable,
- // which sends the read notification, the read observer is notified directly and current
- // value is used instead which doesn't notify. This allow the read observer to read the
- // value and only update the cache once.
- Snapshot.current.readObserver?.invoke(this)
- return currentValue
- }
+ override val value: T
+ get() {
+ // Unlike most state objects, the record list of a derived state can change during a read
+ // because reading updates the cache. To account for this, instead of calling readable,
+ // which sends the read notification, the read observer is notified directly and current
+ // value is used instead which doesn't notify. This allow the read observer to read the
+ // value and only update the cache once.
+ Snapshot.current.readObserver?.invoke(this)
+ return currentValue
+ }
override val currentValue: T
get() = first.withCurrent {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
index b2dcb4e..c8d83d1 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
@@ -1317,7 +1317,7 @@
override fun notifyObjectsInitialized() = currentSnapshot.notifyObjectsInitialized()
- // The following should never be called.
+ /** Should never be called. */
override fun nestedActivated(snapshot: Snapshot) = unsupported()
override fun nestedDeactivated(snapshot: Snapshot) = unsupported()
@@ -1362,8 +1362,10 @@
*/
private val threadSnapshot = SnapshotThreadLocal<Snapshot>()
-// A global synchronization object. This synchronization object should be taken before modifying any
-// of the fields below.
+/**
+ * A global synchronization object. This synchronization object should be taken before modifying any
+ * of the fields below.
+ */
@PublishedApi
internal val lock = Any()
@@ -1372,16 +1374,18 @@
// The following variables should only be written when sync is taken
-// A set of snapshots that are currently open and should be considered invalid for new snapshots.
+/**
+ * A set of snapshots that are currently open and should be considered invalid for new snapshots.
+ */
private var openSnapshots = SnapshotIdSet.EMPTY
-// The first snapshot created must be at least on more than the INVALID_SNAPSHOT
+/** The first snapshot created must be at least on more than the INVALID_SNAPSHOT */
private var nextSnapshotId = INVALID_SNAPSHOT + 1
-// A list of apply observers
+/** A list of apply observers */
private val applyObservers = mutableListOf<(Set<Any>, Snapshot) -> Unit>()
-// A list of observers of writes to the global state.
+/** A list of observers of writes to the global state. */
private val globalWriteObservers = mutableListOf<((Any) -> Unit)>()
private val currentGlobalSnapshot = AtomicReference(
@@ -1393,12 +1397,14 @@
}
)
-// A value to use to initialize the snapshot local variable of writable below. The value of this
-// doesn't matter as it is just used to initialize the local that is immediately overwritten by
-// Snapshot.current. This is done to avoid a compiler error complaining that the var has not been
-// initialized. This can be removed once contracts are out of experimental; then we can mark sync
-// with the correct contracts so the compiler would be able to figure out that the variable is
-// initialized.
+/**
+ * A value to use to initialize the snapshot local variable of writable below. The value of this
+ * doesn't matter as it is just used to initialize the local that is immediately overwritten by
+ * Snapshot.current. This is done to avoid a compiler error complaining that the var has not been
+ * initialized. This can be removed once contracts are out of experimental; then we can mark sync
+ * with the correct contracts so the compiler would be able to figure out that the variable is
+ * initialized.
+ */
@PublishedApi
internal val snapshotInitializer: Snapshot = currentGlobalSnapshot.get()
@@ -1459,17 +1465,19 @@
if (!openSnapshots.get(snapshot.id)) error("Snapshot is not open")
}
+/**
+ * A candidate snapshot is valid if the it is less than or equal to the current snapshot
+ * and it wasn't specifically marked as invalid when the snapshot started.
+ *
+ * All snapshot active at when the snapshot was taken considered invalid for the snapshot
+ * (they have not been applied and therefore are considered invalid).
+ *
+ * All snapshots taken after the current snapshot are considered invalid since they where taken
+ * after the current snapshot was taken.
+ *
+ * INVALID_SNAPSHOT is reserved as an invalid snapshot id.
+ */
private fun valid(currentSnapshot: Int, candidateSnapshot: Int, invalid: SnapshotIdSet): Boolean {
- // A candidate snapshot is valid if the it is less than or equal to the current snapshot
- // and it wasn't specifically marked as invalid when the snapshot started.
- //
- // All snapshot active at when the snapshot was taken considered invalid for the snapshot
- // (they have not been applied and therefore are considered invalid).
- //
- // All snapshots taken after the current snapshot are considered invalid since they where taken
- // after the current snapshot was taken.
- //
- // INVALID_SNAPSHOT is reserved as an invalid snapshot id.
return candidateSnapshot != INVALID_SNAPSHOT && candidateSnapshot <= currentSnapshot &&
!invalid.get(candidateSnapshot)
}