From 4c69877fe2887171f79ae0e843daa5582e0948ba Mon Sep 17 00:00:00 2001 From: Dmytro Date: Wed, 24 Dec 2025 12:00:17 +0100 Subject: [PATCH] implement `InternalCoroutinesApi` --- .../mobile_core/storage/Repository.kt | 50 ++++++++++++------- .../mobile_core/storage/SettingsExt.kt | 24 ++++++--- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/Repository.kt b/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/Repository.kt index bfeb28b..662216a 100644 --- a/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/Repository.kt +++ b/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/Repository.kt @@ -16,37 +16,51 @@ class Repository(private val storage: Settings) { } var tcData: IABData - get() = storage.keys - .filter { it.startsWith(TCF_PREFIX) } - .associateWith { storage[it]!! } + get() = storage.withLock { + keys + .filter { it.startsWith(TCF_PREFIX) } + .associateWith { this[it]!! } + } set(value) { - storage.removeKeysStartingWith(prefix = TCF_PREFIX) - value.entries.forEach { storage[it.key] = it.value } + storage.withLock { + removeKeysStartingWith(prefix = TCF_PREFIX) + value.entries.forEach { this[it.key] = it.value } + } } var gppData: IABData - get() = storage.keys - .filter { it.startsWith(GPP_PREFIX) } - .associateWith { storage[it]!! } + get() = storage.withLock { + keys + .filter { it.startsWith(GPP_PREFIX) } + .associateWith { this[it]!! } + } set(value) { - storage.removeKeysStartingWith(prefix = GPP_PREFIX) - value.entries.forEach { storage[it.key] = it.value } + storage.withLock { + removeKeysStartingWith(prefix = GPP_PREFIX) + value.entries.forEach { this[it.key] = it.value } + } } var uspString: String? - get() = storage[USPSTRING_KEY] - set(value) { storage[USPSTRING_KEY] = value } + get() = storage.withLock { this[USPSTRING_KEY] } + set(value) { storage.withLock { this[USPSTRING_KEY] = value } } var state: State? get() = runCatching { - Json.decodeFromString(storage.getString(SP_STATE_KEY, defaultValue = "")) + storage.withLock { + Json.decodeFromString(getString(SP_STATE_KEY, defaultValue = "")) + } }.getOrNull() - set(value) { storage[SP_STATE_KEY] = Json.encodeToString(value) } + set(value) { + storage.withLock { this[SP_STATE_KEY] = Json.encodeToString(value) } + } fun clear() { - storage.removeKeysStartingWith(prefix = TCF_PREFIX) - storage.removeKeysStartingWith(prefix = GPP_PREFIX) - storage.remove(USPSTRING_KEY) - storage.remove(SP_STATE_KEY) + storage.withLock { + removeKeysStartingWith(prefix = TCF_PREFIX) + removeKeysStartingWith(prefix = GPP_PREFIX) + remove(USPSTRING_KEY) + remove(SP_STATE_KEY) + } } } diff --git a/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/SettingsExt.kt b/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/SettingsExt.kt index 4d5909a..75a7093 100644 --- a/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/SettingsExt.kt +++ b/core/src/commonMain/kotlin/com/sourcepoint/mobile_core/storage/SettingsExt.kt @@ -3,6 +3,9 @@ package com.sourcepoint.mobile_core.storage import com.russhwolf.settings.Settings import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.internal.SynchronizedObject +import kotlinx.coroutines.internal.synchronized import com.russhwolf.settings.set as originalSet import com.russhwolf.settings.get as originalGet import kotlinx.serialization.json.JsonNull @@ -18,15 +21,20 @@ import kotlinx.serialization.json.intOrNull import kotlinx.serialization.json.long import kotlinx.serialization.json.longOrNull -private val settingsMutex = kotlinx.coroutines.sync.Mutex() +@OptIn(InternalCoroutinesApi::class) +private val settingsLock = SynchronizedObject() -internal fun Settings.removeKeysStartingWith(prefix: String) { - runBlocking { - settingsMutex.withLock { - val toRemove = keys.filter { it.startsWith(prefix) } - toRemove.forEach { remove(it) } - } - } +@OptIn(InternalCoroutinesApi::class) +internal fun synchronizedLock(lock: SynchronizedObject, block: () -> T): T = synchronized(lock, block) + +@OptIn(InternalCoroutinesApi::class) +internal fun Settings.withLock(block: Settings.() -> T): T = synchronizedLock(settingsLock) { + block() +} + +internal fun Settings.removeKeysStartingWith(prefix: String) = withLock { + val toRemove = keys.filter { it.startsWith(prefix) } + toRemove.forEach { remove(it) } } internal operator fun Settings.set(key: String, value: JsonPrimitive) = putJsonPrimitive(key, value)