Colton Idle
08/07/2022, 1:21 AMwithContext(Dispatchers.Default){ConcurrentModificationExceptionindexOfFirstephemient
08/07/2022, 1:28 AMephemient
08/07/2022, 1:29 AMColton Idle
08/07/2022, 1:30 AMColton Idle
08/07/2022, 1:30 AMephemient
08/07/2022, 1:30 AMephemient
08/07/2022, 1:31 AMColton Idle
08/07/2022, 1:33 AMval indexOfPlace = appState.fullList.indexOfFirst { it.id == placeUid }ephemient
08/07/2022, 1:35 AMColton Idle
08/07/2022, 1:36 AMColton Idle
08/07/2022, 1:37 AMephemient
08/07/2022, 1:39 AMCopyOnWriteArrayListColton Idle
08/07/2022, 1:56 AMColton Idle
08/10/2022, 9:40 PMephemient
08/11/2022, 1:07 AMephemient
08/11/2022, 1:35 AMMapindexOfFirstColton Idle
08/11/2022, 2:28 AMyou can only read a data structure in multiple threads if it's immutable or if it's known to be thread-safe (which List isn't)TIL. I thought that you can red a data structure in multiple threads if you basically know when each thread is calling which. which in this case I thought that'd be safe because even though im switching threads, im trying to be procedural about the whole thing.
Colton Idle
08/11/2022, 2:29 AMif you can makeokay. that makes sense. So the list is immutable, but I can change the list that I'm referencing overall from other threads?into aappState.fullListOfTodos, then that is safe to update from other threads.MutableState<List<Model>>
Colton Idle
08/11/2022, 2:30 AMthen you just keep everything else immutable, and process all the mutation on a single threadwait. so doesn't this just go against what you just said of "then that is safe to update from other threads."
Colton Idle
08/11/2022, 2:32 AM(I've also taken the liberty of using ayeah. I was definitely getting to the point where I wanted to use a map. but as an excercise I wanted to see how I can do this performantly with just a list. as my crux of the issue has been that indexOfFirst is slow (of course) with a large list, and so I was like "oh wait. coroutines makes this a piece of cake"to eliminate the need to scan withMapfor each item)indexOfFirst
ephemient
08/11/2022, 2:50 AMColton Idle
08/11/2022, 2:55 AMColton Idle
08/11/2022, 2:55 AMephemient
08/11/2022, 2:57 AMephemient
08/11/2022, 2:59 AMList(100) { SomeBigObject() }.toList()SomeBigObjectColton Idle
08/11/2022, 3:03 AMesults in two lists (at least temporarily), each with a backing array of size (at least) 100, but there's only 100🤯 why hasn't that occurred to me? lol. okay cool. wow. so many TILs.instances across themSomeBigObject
Colton Idle
08/11/2022, 3:05 AMappState.fullListOfTodosMutableState<List<Model>>Colton Idle
08/11/2022, 3:06 AMColton Idle
08/11/2022, 4:33 AMappState.fullListOfTodosMutableState<List<Model>>//this search for index could take a long time, so move to CPU bound Dispatcher
                withContext(Dispatchers.Default) {
                
                  // The crash/exception happens on this line VVV
                  indexOfTodo =
                    appState.fullListOfTodos.indexOfFirst { it.id == todo.id }
                  place = appState.fullListOfTodos[indexOfTodo]
                  updatedTodo = TodoModel(//update a few fields)
                }
                // If I remove this line, the crash/exception does not happen VV
                appState.fullListOfTodos[indexOfTodo] = updatedTodowithContext(Dispatchers.Default) {
                
                  indexOfTodo =
                    appState.fullListOfTodos.indexOfFirst { it.id == todo.id }
                  place = appState.fullListOfTodos[indexOfTodo]
                  updatedTodo = TodoModel(//update a few fields)
                  val newList = appState.fullListOfTodos.toMutableList().apply { this[indexOfTodo] = updatedTodo }
                  appState.fullListOfTodos = newList
                }Colton Idle
08/11/2022, 4:47 AMindexOfTodo = appState.fullListOfTodos.indexOfFirst { it.id == todo.id }indexOfTodo = appState.fullListOfTodos.toList().indexOfFirst { it.id == todo.id }Colton Idle
08/11/2022, 4:48 AMephemient
08/11/2022, 4:52 AM.toList().indexOfFirstephemient
08/11/2022, 4:55 AM.toList().indexOfFirst {...}.indexOfFirst {...}.toList().indexOfFirst {...}.indexOfFirst {...}.toList.indexOfFirstColton Idle
08/11/2022, 6:09 AMdamn. maybe its just happening so quickly that its not triggering a CME in my testing. thanks for the heads up on that.there doesn't make a difference. it creates another copy, but that requires iterating and reading the list just the same as.toList()does, and will fail if the list is concurrently mutated.indexOfFirst
Colton Idle
08/11/2022, 6:11 AMeither your list isn't being concurrently mutatedin my original SO question I still don't see how it's being concurrently mutated honestly.
Colton Idle
08/11/2022, 6:12 AMephemient
08/11/2022, 6:48 AMephemient
08/11/2022, 6:51 AMColton Idle
08/11/2022, 6:53 AMephemient
08/11/2022, 6:55 AMColton Idle
08/11/2022, 6:55 AMappState.fullListOfTodosMutableState<List<Model>>//this search for index could take a long time, so move to CPU bound Dispatcher
                withContext(Dispatchers.Default) {
                
                  // The crash/exception happens on this line VVV
                  indexOfTodo =
                    appState.fullListOfTodos.indexOfFirst { it.id == todo.id }
                  place = appState.fullListOfTodos[indexOfTodo]
                  updatedTodo = TodoModel(//update a few fields)
                }
                // If I remove this line, the crash/exception does not happen VV
                appState.fullListOfTodos[indexOfTodo] = updatedTodowithContext(Dispatchers.Default) {
                
                  indexOfTodo =
                    appState.fullListOfTodos.indexOfFirst { it.id == todo.id }
                  place = appState.fullListOfTodos[indexOfTodo]
                  updatedTodo = TodoModel(//update a few fields)
                  val newList = appState.fullListOfTodos.toMutableList().apply { this[indexOfTodo] = updatedTodo }
                  appState.fullListOfTodos = newList
                }ephemient
08/11/2022, 6:59 AMephemient
08/11/2022, 7:06 AMephemient
08/11/2022, 7:09 AMephemient
08/11/2022, 7:11 AMColton Idle
08/11/2022, 7:34 AMColton Idle
08/11/2022, 7:36 AMColton Idle
08/11/2022, 7:59 AMephemient
08/11/2022, 8:05 AMColton Idle
08/11/2022, 8:10 AMephemient
08/11/2022, 8:10 AMephemient
08/11/2022, 8:10 AMephemient
08/11/2022, 8:12 AMephemient
08/11/2022, 8:13 AMephemient
08/11/2022, 8:16 AMColton Idle
08/11/2022, 8:31 AMColton Idle
08/11/2022, 8:34 AMColton Idle
08/11/2022, 8:35 AMephemient
08/11/2022, 12:24 PMColton Idle
08/11/2022, 12:26 PMephemient
08/11/2022, 12:32 PMsomeFlow.runningFold(initial, transform)flow {
    var accumulator = initial
    emit(accumulator)
    someFlow.collect { value ->
        accumulator = transform(accumulator, value)
        emit(accumulator)
    }
}ephemient
08/11/2022, 12:33 PMsomeFlow.launchIn(scope)scope.launch {
    someFlow.collect()
}Colton Idle
08/11/2022, 12:35 PM