refactor: drop java.util.concurrent atomics from commonMain

Phase 2 of the iOS plan — two of the ~9 small migrations to clear
java.* imports out of commons/commonMain.

- ChessLobbyState: the AtomicLong stateVersionCounter only existed to
  bump a MutableStateFlow<Long>. MutableStateFlow.update is itself
  atomic, so the counter is redundant — replaced with
  _stateVersion.update { it + 1 }. Removes the dep and simplifies the
  code.
- SigningState (GlobalSigningStatus): AtomicInteger is doing real
  cross-thread coordination. Migrated to kotlin.concurrent.atomics.
  AtomicInt (KMP stdlib). The common-API method names differ from
  AtomicInteger — addAndFetch(±1) / store(0) instead of
  incrementAndGet / decrementAndGet / set.
This commit is contained in:
Claude
2026-05-24 18:11:20 +00:00
parent 78ef4fa672
commit 1b6b699d76
2 changed files with 14 additions and 15 deletions
@@ -29,7 +29,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import java.util.concurrent.atomic.AtomicLong
/**
* Challenge expiry: 24 hours
@@ -245,9 +244,9 @@ class ChessLobbyState(
private val _selectedGameId = MutableStateFlow<String?>(null)
val selectedGameId: StateFlow<String?> = _selectedGameId.asStateFlow()
// State version counter - increments on every game state update
// UI can observe this to force recomposition when internal state changes
private val stateVersionCounter = AtomicLong(0)
// State version counter — bumped on every game state update so the UI
// can force recomposition when internal state changes. MutableStateFlow.update
// is itself atomic, so a separate counter is not needed.
private val _stateVersion = MutableStateFlow(0L)
val stateVersion: StateFlow<Long> = _stateVersion.asStateFlow()
@@ -383,13 +382,11 @@ class ChessLobbyState(
if (inActiveGames) {
_activeGames.update { it + (gameId to stateToUse) }
// Increment version to force UI recomposition even if map equals() returns true
val newVersion = stateVersionCounter.incrementAndGet()
_stateVersion.value = newVersion
// Bump version to force UI recomposition even if map equals() returns true
_stateVersion.update { it + 1 }
} else if (inSpectatingGames) {
_spectatingGames.update { it + (gameId to stateToUse) }
val newVersion = stateVersionCounter.incrementAndGet()
_stateVersion.value = newVersion
_stateVersion.update { it + 1 }
}
}
@@ -27,7 +27,8 @@ import androidx.compose.runtime.setValue
import com.vitorpamplona.quartz.nip01Core.signers.SignerExceptions
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.coroutines.cancellation.CancellationException
sealed class SigningOpState {
@@ -44,26 +45,27 @@ sealed class SigningOpState {
* Global signing status — any [SigningState] instance updates this when signing starts/ends.
* Observe [globalState] from a screen-level composable to show a persistent status bar.
*/
@OptIn(ExperimentalAtomicApi::class)
object GlobalSigningStatus {
var globalState by mutableStateOf<SigningOpState>(SigningOpState.Idle)
private set
private val activeCount = AtomicInteger(0)
private val activeCount = AtomicInt(0)
fun onPending() {
activeCount.incrementAndGet()
activeCount.addAndFetch(1)
globalState = SigningOpState.Pending
}
fun onIdle() {
if (activeCount.decrementAndGet() <= 0) {
activeCount.set(0)
if (activeCount.addAndFetch(-1) <= 0) {
activeCount.store(0)
globalState = SigningOpState.Idle
}
}
fun onError(message: String) {
activeCount.decrementAndGet()
activeCount.addAndFetch(-1)
globalState = SigningOpState.Error(message)
}
}