Migrate j.u.c.a atomics usages to k.c.a (#2207)
This commit is contained in:
1 parent
1aa1addcf7
commit
aacde8871e
10 files changed
+76
-43
No files matched your search
@@ -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 ->
|
||||
|
||||
Reference in new issue
Block a user