Skip to content

Instantly share code, notes, and snippets.

@zach-klippenstein
Last active May 23, 2022 11:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zach-klippenstein/cbcfa3e1076ec0fa088d0bed87369080 to your computer and use it in GitHub Desktop.
Save zach-klippenstein/cbcfa3e1076ec0fa088d0bed87369080 to your computer and use it in GitHub Desktop.
Sample code for my "Implementing snapshot-aware data structures" blog post.
import androidx.compose.runtime.mutableStateOf
import kotlin.test.assertEquals
import org.junit.Test
class SnapshotStateObjectWalkthrough {
@Test
fun walkthrough() {
// Code not running in an explicit snapshot is
// considered to be in the "global snapshot".
val message = mutableStateOf("")
// Create a snapshot that is a child of the global snapshot.
val snapA = Snapshot.takeMutableSnapshot()
snapA.enter {
message.value += "Hello"
// Changes performed inside a snapshot are
// immediately visible within that snapshot.
assertEquals("Hello", message.value)
}
// Any changes performed in a snapshot are not visible
// to its parent snapshot or any other snapshots until the
// snapshot is applied.
assertEquals("", message.value)
// Create another snapshot. Since this is outside the
// snapA.enter, it's a child of the global snapshot,
// and isolated from snapA.
val snapB = Snapshot.takeMutableSnapshot()
snapB.enter {
message.value += "world"
assertEquals("world", message.value)
}
assertEquals("", message.value)
// Because we never disposed snapA, we can re-enter
// it and see the world as it was at the end of the last
// enter call.
snapA.enter {
message.value += " friend"
assertEquals("Hello friend", message.value)
}
// And still, nothing is visible outside the snapshot.
assertEquals("", message.value)
// Now we're done with snapA, so let's apply it…
snapA.apply()
// …and cleanup after it.
snapA.dispose()
// And now all its changes are visible to the parent, i.e.
// the global snapshot!
assertEquals("Hello friend", message.value)
// We don't care about snapB anymore, so let's
// just dispose it without applying. It will be as if it
// never existed, and none of the changes it made ever
// happened.
snapB.dispose()
// Create one more new snapshot.
val snapC = Snapshot.takeMutableSnapshot()
snapC.enter {
message.value = "goodbye"
}
snapC.apply()
snapC.dispose()
assertEquals("goodbye", message.value)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment