Migrate j.u.c.a atomics usages to k.c.a (#2207)

This commit is contained in:
renovate[bot] authored and GitHub committed 2025-03-21 12:27:38 +00:00
1 parent 1aa1addcf7
commit aacde8871e
10 files changed
+76 -43

No files matched your search

+1
View File
@@ -274,6 +274,7 @@ kotlin {
"androidx.compose.animation.ExperimentalSharedTransitionApi",
"androidx.paging.ExperimentalPagingApi",
"kotlin.ExperimentalStdlibApi",
"kotlin.concurrent.atomics.ExperimentalAtomicApi",
"kotlin.contracts.ExperimentalContracts",
"kotlinx.coroutines.ExperimentalCoroutinesApi",
"kotlinx.coroutines.FlowPreview",
@@ -1,7 +1,6 @@
package com.hippo.ehviewer.gallery
import androidx.collection.SieveCache
import arrow.atomic.value
import arrow.fx.coroutines.ExitCase
import arrow.fx.coroutines.bracketCase
import com.hippo.ehviewer.EhDB
@@ -13,8 +12,8 @@ import com.hippo.ehviewer.util.OSUtils
import com.hippo.ehviewer.util.detectAds
import com.hippo.ehviewer.util.displayString
import com.hippo.ehviewer.util.isAtLeastO
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.read
import kotlin.concurrent.write
import kotlinx.coroutines.CoroutineScope
@@ -50,7 +49,7 @@ abstract class PageLoader(val scope: CoroutineScope, val gid: Long, startPage: I
fun decodePreloadRange(index: Int) = index - 3..index + 3
fun needDecode(index: Int) = index in decodePreloadRange(prevIndex) &&
fun needDecode(index: Int) = index in decodePreloadRange(prevIndex.load()) &&
lock.read { index !in cache } &&
pages[index].status !is PageStatus.Ready &&
pages[index].status !is PageStatus.Blocked
@@ -79,7 +78,7 @@ abstract class PageLoader(val scope: CoroutineScope, val gid: Long, startPage: I
pages.forEach(Page::reset)
}
private var prevIndex by AtomicInteger(-1)::value
private val prevIndex = AtomicInt(-1)
fun retryPage(index: Int, orgImg: Boolean = false) {
notifyPageWait(index)
@@ -131,12 +130,12 @@ abstract class PageLoader(val scope: CoroutineScope, val gid: Long, startPage: I
}
fun request(index: Int) {
val prefetchRange = if (index >= prevIndex) {
val prefetchRange = if (index >= prevIndex.load()) {
index + 1..(index + prefetchPageCount).coerceAtMost(size - 1)
} else {
index - 1 downTo (index - prefetchPageCount).coerceAtLeast(0)
}
prevIndex = index
prevIndex.store(index)
val image = lock.read { cache[index] }
if (image != null) {
notifyPageSucceed(index, image, false)
@@ -47,19 +47,21 @@ import com.hippo.ehviewer.ktbuilder.execute
import com.hippo.ehviewer.ktbuilder.imageRequest
import com.hippo.ehviewer.util.isAtLeastP
import com.hippo.ehviewer.util.isAtLeastU
import com.hippo.ehviewer.util.updateAndGet
import com.hippo.files.openFileDescriptor
import com.hippo.files.toUri
import java.nio.ByteBuffer
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.decrementAndFetch
import okio.Path
import splitties.init.appCtx
class Image private constructor(image: CoilImage, private val src: ImageSource) {
val refcnt = AtomicInteger(1)
val refcnt = AtomicInt(1)
fun pin() = refcnt.updateAndGet { if (it != 0) it + 1 else 0 } != 0
fun unpin() = (refcnt.decrementAndGet() == 0).also { if (it) recycle() }
fun unpin() = (refcnt.decrementAndFetch() == 0).also { if (it) recycle() }
val intrinsicSize = with(image) { IntSize(width, height) }
val allocationSize = image.size
@@ -2,7 +2,6 @@ package com.hippo.ehviewer.spider
import androidx.collection.MutableObjectIntMap
import androidx.collection.mutableObjectIntMapOf
import arrow.atomic.Atomic
import arrow.fx.coroutines.fixedRate
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.executeSafely
@@ -15,6 +14,7 @@ import io.ktor.client.plugins.timeout
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.HttpStatement
import kotlin.concurrent.atomics.AtomicReference
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.time.Duration
@@ -70,7 +70,7 @@ suspend inline fun <R> timeoutBySpeed(
crossinline f: suspend (HttpResponse) -> R,
noinline t: OnTimeout = { throw it },
) = coroutineScope {
val onTimeout = Atomic<OnTimeout?>(t).let { { e: IOException -> it.getAndSet(null)?.invoke(e) } }
val onTimeout = AtomicReference<OnTimeout?>(t).let { { e: IOException -> it.exchange(null)?.invoke(e) } }
val watchdog = launch {
delay(Settings.connTimeout.seconds)
onTimeout(ConnectTimeoutException(url, Settings.connTimeout * 1000L))
@@ -40,7 +40,9 @@ import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
import com.hippo.ehviewer.util.displayString
import com.hippo.files.find
import eu.kanade.tachiyomi.util.system.logcat
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.decrementAndFetch
import kotlin.concurrent.atomics.incrementAndFetch
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.TimeSource
import kotlinx.coroutines.CancellationException
@@ -71,8 +73,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
val spiderDen: SpiderDen = SpiderDen(galleryInfo)
private val mPageStateLock = Any()
private val mDownloadedPages = AtomicInteger(0)
private val mFinishedPages = AtomicInteger(0)
private val mDownloadedPages = AtomicInt(0)
private val mFinishedPages = AtomicInt(0)
private val mSpiderListeners: MutableList<OnSpiderListener> = ArrayList()
private var mReadReference = 0
@@ -116,8 +118,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
mSpiderListeners.forEach {
it.onPageSuccess(
index,
mFinishedPages.get(),
mDownloadedPages.get(),
mFinishedPages.load(),
mDownloadedPages.load(),
pageStates.size,
)
}
@@ -130,8 +132,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
it.onPageFailure(
index,
error,
mFinishedPages.get(),
mDownloadedPages.get(),
mFinishedPages.load(),
mDownloadedPages.load(),
pageStates.size,
)
}
@@ -142,8 +144,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
synchronized(mSpiderListeners) {
mSpiderListeners.forEach {
it.onFinish(
mFinishedPages.get(),
mDownloadedPages.get(),
mFinishedPages.load(),
mDownloadedPages.load(),
pageStates.size,
)
}
@@ -182,8 +184,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
}
i++
}
mDownloadedPages.lazySet(0)
mFinishedPages.lazySet(0)
mDownloadedPages.store(0)
mFinishedPages.store(0)
}
mWorkerScope.enterDownloadMode()
}
@@ -401,14 +403,14 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
val oldState = pageStates[index]
pageStates[index] = state
if (!isStateDone(oldState) && isStateDone(state)) {
mDownloadedPages.incrementAndGet()
mDownloadedPages.incrementAndFetch()
} else if (isStateDone(oldState) && !isStateDone(state)) {
mDownloadedPages.decrementAndGet()
mDownloadedPages.decrementAndFetch()
}
if (oldState != STATE_FINISHED && state == STATE_FINISHED) {
mFinishedPages.incrementAndGet()
mFinishedPages.incrementAndFetch()
} else if (oldState == STATE_FINISHED && state != STATE_FINISHED) {
mFinishedPages.decrementAndGet()
mFinishedPages.decrementAndFetch()
}
}
@@ -418,8 +420,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
} else if (state == STATE_FINISHED) {
notifyPageSuccess(index)
}
if (mDownloadedPages.get() == size) {
if (mFinishedPages.get() == size) archiveJob.start()
if (mDownloadedPages.load() == size) {
if (mFinishedPages.load() == size) archiveJob.start()
notifyAllPageDownloaded()
}
}
@@ -33,7 +33,6 @@ import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.dp
import arrow.atomic.Atomic
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.settings.PreferenceTokens.PreferenceTextPadding
import com.hippo.ehviewer.util.ProgressDialog
@@ -44,6 +43,7 @@ import com.jamal.composeprefs3.ui.prefs.SwitchPref
import com.jamal.composeprefs3.ui.prefs.TextPref
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.spec.DirectionDestinationSpec
import kotlin.concurrent.atomics.AtomicReference
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlin.math.roundToInt
@@ -152,8 +152,8 @@ fun WorkPreference(title: String, summary: String? = null, work: suspend Corouti
@Composable
fun <I, O> LauncherPreference(title: String, summary: String? = null, contract: ActivityResultContract<I, O>, key: I, work: suspend CoroutineScope.(O) -> Unit) {
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
val callback = remember { Atomic<(O) -> Unit> {} }
val launcher = rememberLauncherForActivityResult(contract = contract) { callback.getAndSet { }.invoke(it) }
val callback = remember { AtomicReference<(O) -> Unit> {} }
val launcher = rememberLauncherForActivityResult(contract = contract) { callback.exchange { }.invoke(it) }
var completed by remember { mutableStateOf(true) }
if (!completed) {
ProgressDialog()
@@ -161,7 +161,7 @@ fun <I, O> LauncherPreference(title: String, summary: String? = null, contract:
Preference(title = title, summary = summary) {
coroutineScope.launch {
val o = suspendCoroutine { cont ->
callback.set { cont.resume(it) }
callback.store { cont.resume(it) }
launcher.launch(key)
}
completed = false
@@ -20,8 +20,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import arrow.atomic.Atomic
import arrow.atomic.value
import com.google.accompanist.web.WebView
import com.google.accompanist.web.rememberWebViewState
import com.hippo.ehviewer.R
@@ -32,6 +30,7 @@ import com.hippo.ehviewer.util.setDefaultSettings
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlin.concurrent.atomics.AtomicReference
private const val APPLY_JS = "javascript:(function(){var apply = document.getElementById(\"apply\").children[0];apply.click();})();"
@@ -39,7 +38,7 @@ private const val APPLY_JS = "javascript:(function(){var apply = document.getEle
@Composable
fun AnimatedVisibilityScope.UConfigScreen(navigator: DestinationsNavigator) = Screen(navigator) {
val url = EhUrl.uConfigUrl
var webview by remember { Atomic<WebView?>(null)::value }
val webview = remember { AtomicReference<WebView?>(null) }
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
topBar = {
@@ -53,7 +52,7 @@ fun AnimatedVisibilityScope.UConfigScreen(navigator: DestinationsNavigator) = Sc
actions = {
IconButton(
onClick = {
webview?.loadUrl(APPLY_JS)
webview.load()?.loadUrl(APPLY_JS)
navigator.popBackStack()
},
) {
@@ -69,7 +68,7 @@ fun AnimatedVisibilityScope.UConfigScreen(navigator: DestinationsNavigator) = Sc
state = state,
modifier = Modifier.padding(paddingValues).fillMaxSize(),
onCreated = { it.setDefaultSettings() },
factory = { WebView(it).apply { webview = this } },
factory = { WebView(it).apply { webview.store(this) } },
)
val applyTip = stringResource(id = R.string.apply_tip)
LaunchedEffect(Unit) { snackbarHostState.showSnackbar(applyTip) }
@@ -16,7 +16,8 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Shape
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.fetchAndIncrement
val NoopTransitionsVisibilityScope = TransitionsVisibilityScope(emptySet())
@@ -73,14 +74,14 @@ fun initSETConnection() {
listThumbGenerator connectTo detailThumbGenerator
}
private val atomicIncId = AtomicInteger()
private val atomicIncId = AtomicInt(0)
class SETNodeGenerator {
private val tracker = hashMapOf<String, SETNode>()
private val opposites = mutableListOf<SETNodeGenerator>()
fun summon(contentKey: String): SETNode {
val node = opposites.firstNotNullOfOrNull { it.tracker[contentKey] } ?: SETNode(contentKey = contentKey, uniqueID = "${atomicIncId.getAndIncrement()}")
val node = opposites.firstNotNullOfOrNull { it.tracker[contentKey] } ?: SETNode(contentKey = contentKey, uniqueID = "${atomicIncId.fetchAndIncrement()}")
tracker[contentKey] = node
return node
}
@@ -0,0 +1,28 @@
package com.hippo.ehviewer.util
import kotlin.concurrent.atomics.AtomicInt
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
inline fun AtomicInt.loop(action: (Int) -> Unit): Nothing {
contract { callsInPlace(action, InvocationKind.AT_LEAST_ONCE) }
do {
action(load())
} while (true)
}
inline fun <R> AtomicInt.update(function: (Int) -> Int, transform: (old: Int, new: Int) -> R): R {
contract {
callsInPlace(function, InvocationKind.AT_LEAST_ONCE)
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
loop { cur ->
val upd = function(cur)
if (compareAndSet(cur, upd)) return transform(cur, upd)
}
}
inline fun AtomicInt.updateAndGet(function: (Int) -> Int): Int {
contract { callsInPlace(function, InvocationKind.AT_LEAST_ONCE) }
return update(function) { _, new -> new }
}
@@ -20,16 +20,17 @@ import androidx.core.content.FileProvider
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import arrow.atomic.AtomicInt
import com.hippo.ehviewer.R
import eu.kanade.tachiyomi.util.lang.withUIContext
import java.io.File
import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.fetchAndIncrement
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
// Fuck off the silly Android launcher and callback :)
private val atomicInteger = AtomicInt()
private val atomicInteger = AtomicInt(0)
private val Context.lifecycle: Lifecycle
get() {
@@ -44,7 +45,7 @@ private val Context.lifecycle: Lifecycle
}
suspend fun <I, O> Context.awaitActivityResult(contract: ActivityResultContract<I, O>, input: I): O {
val key = "activity_rq#${atomicInteger.getAndIncrement()}"
val key = "activity_rq#${atomicInteger.fetchAndIncrement()}"
var launcher: ActivityResultLauncher<I>? = null
var observer: LifecycleEventObserver? = null
observer = LifecycleEventObserver { _, event ->