File tree Expand file tree Collapse file tree 2 files changed +41
-1
lines changed
compose/runtime/runtime/src
commonMain/kotlin/androidx/compose/runtime/snapshots
test/kotlin/androidx/compose/runtime/snapshots Expand file tree Collapse file tree 2 files changed +41
-1
lines changed Original file line number Diff line number Diff line change @@ -53,7 +53,9 @@ class SnapshotStateObserver(private val onChangedExecutor: (callback: () -> Unit
5353 */
5454 private val readObserver: (Any ) -> Unit = { state ->
5555 if (! isPaused) {
56- currentMap!! .addValue(state)
56+ synchronized(applyMaps) {
57+ currentMap!! .addValue(state)
58+ }
5759 }
5860 }
5961
Original file line number Diff line number Diff line change @@ -324,6 +324,44 @@ class SnapshotStateObserverTests {
324324 assertNull(threadException)
325325 }
326326
327+ @Test // regression test for 192677711, second case
328+ fun tryToReproduceSecondRaceCondtion () {
329+ var running = true
330+ var threadException: Exception ? = null
331+ try {
332+ thread {
333+ try {
334+ while (running) {
335+ Snapshot .sendApplyNotifications()
336+ }
337+ } catch (e: Exception ) {
338+ threadException = e
339+ }
340+ }
341+
342+ for (i in 1 .. 10000 ) {
343+ val state1 by mutableStateOf(0 )
344+ var state2 by mutableStateOf(true )
345+ val observer = SnapshotStateObserver ({}).apply {
346+ start()
347+ }
348+ observer.observeReads(Unit , {}) {
349+ repeat(1000 ) {
350+ @Suppress(" UNUSED_EXPRESSION" )
351+ state1
352+ if (state2) {
353+ state2 = false
354+ }
355+ }
356+ }
357+ assertNull(threadException)
358+ }
359+ } finally {
360+ running = false
361+ }
362+ assertNull(threadException)
363+ }
364+
327365 private fun runSimpleTest (
328366 block : (modelObserver: SnapshotStateObserver , data: MutableState <Int >) -> Unit
329367 ) {
You can’t perform that action at this time.
0 commit comments