Update kotlin monorepo to v2.1.20 (#1883)

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit 556290f2d35f739bb4bddc012739acf10b92708d)
This commit is contained in:
Mend Renovate 2025-03-31 06:05:38 +02:00 committed by Jobobby04
parent e80cb1795e
commit 027f179a4b
7 changed files with 51 additions and 33 deletions

View File

@ -101,9 +101,12 @@ import java.time.Instant
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean import kotlin.concurrent.atomics.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.concurrent.atomics.incrementAndFetch
@OptIn(ExperimentalAtomicApi::class)
class LibraryUpdateJob(private val context: Context, workerParams: WorkerParameters) : class LibraryUpdateJob(private val context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) { CoroutineWorker(context, workerParams) {
@ -343,7 +346,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
*/ */
private suspend fun updateChapterList() { private suspend fun updateChapterList() {
val semaphore = Semaphore(5) val semaphore = Semaphore(5)
val progressCount = AtomicInteger(0) val progressCount = AtomicInt(0)
val currentlyUpdatingManga = CopyOnWriteArrayList<Manga>() val currentlyUpdatingManga = CopyOnWriteArrayList<Manga>()
val newUpdates = CopyOnWriteArrayList<Pair<Manga, Array<Chapter>>>() val newUpdates = CopyOnWriteArrayList<Pair<Manga, Array<Chapter>>>()
val failedUpdates = CopyOnWriteArrayList<Pair<Manga, String?>>() val failedUpdates = CopyOnWriteArrayList<Pair<Manga, String?>>()
@ -408,7 +411,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
if (chaptersToDownload.isNotEmpty()) { if (chaptersToDownload.isNotEmpty()) {
downloadChapters(manga, chaptersToDownload) downloadChapters(manga, chaptersToDownload)
hasDownloads.set(true) hasDownloads.store(true)
} }
libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size } libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size }
@ -441,7 +444,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
if (newUpdates.isNotEmpty()) { if (newUpdates.isNotEmpty()) {
notifier.showUpdateNotifications(newUpdates) notifier.showUpdateNotifications(newUpdates)
if (hasDownloads.get()) { if (hasDownloads.load()) {
downloadManager.startDownloads() downloadManager.startDownloads()
} }
} }
@ -641,7 +644,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
private suspend fun withUpdateNotification( private suspend fun withUpdateNotification(
updatingManga: CopyOnWriteArrayList<Manga>, updatingManga: CopyOnWriteArrayList<Manga>,
completed: AtomicInteger, completed: AtomicInt,
manga: Manga, manga: Manga,
block: suspend () -> Unit, block: suspend () -> Unit,
) = coroutineScope { ) = coroutineScope {
@ -650,7 +653,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
updatingManga.add(manga) updatingManga.add(manga)
notifier.showProgressNotification( notifier.showProgressNotification(
updatingManga, updatingManga,
completed.get(), completed.load(),
mangaToUpdate.size, mangaToUpdate.size,
) )
@ -659,10 +662,10 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
ensureActive() ensureActive()
updatingManga.remove(manga) updatingManga.remove(manga)
completed.getAndIncrement() completed.incrementAndFetch()
notifier.showProgressNotification( notifier.showProgressNotification(
updatingManga, updatingManga,
completed.get(), completed.load(),
mangaToUpdate.size, mangaToUpdate.size,
) )
} }

View File

@ -37,8 +37,11 @@ import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.concurrent.atomics.fetchAndIncrement
@OptIn(ExperimentalAtomicApi::class)
class MetadataUpdateJob(private val context: Context, workerParams: WorkerParameters) : class MetadataUpdateJob(private val context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) { CoroutineWorker(context, workerParams) {
@ -97,7 +100,7 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
private suspend fun updateMetadata() { private suspend fun updateMetadata() {
val semaphore = Semaphore(5) val semaphore = Semaphore(5)
val progressCount = AtomicInteger(0) val progressCount = AtomicInt(0)
val currentlyUpdatingManga = CopyOnWriteArrayList<Manga>() val currentlyUpdatingManga = CopyOnWriteArrayList<Manga>()
coroutineScope { coroutineScope {
@ -142,7 +145,7 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
private suspend fun withUpdateNotification( private suspend fun withUpdateNotification(
updatingManga: CopyOnWriteArrayList<Manga>, updatingManga: CopyOnWriteArrayList<Manga>,
completed: AtomicInteger, completed: AtomicInt,
manga: Manga, manga: Manga,
block: suspend () -> Unit, block: suspend () -> Unit,
) = coroutineScope { ) = coroutineScope {
@ -151,7 +154,7 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
updatingManga.add(manga) updatingManga.add(manga)
notifier.showProgressNotification( notifier.showProgressNotification(
updatingManga, updatingManga,
completed.get(), completed.load(),
mangaToUpdate.size, mangaToUpdate.size,
) )
@ -160,10 +163,10 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
ensureActive() ensureActive()
updatingManga.remove(manga) updatingManga.remove(manga)
completed.getAndIncrement() completed.fetchAndIncrement()
notifier.showProgressNotification( notifier.showProgressNotification(
updatingManga, updatingManga,
completed.get(), completed.load(),
mangaToUpdate.size, mangaToUpdate.size,
) )
} }

View File

@ -12,16 +12,18 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Collections import java.util.Collections
import java.util.concurrent.atomic.AtomicReference import kotlin.concurrent.atomics.AtomicReference
import kotlin.concurrent.atomics.ExperimentalAtomicApi
/** /**
* Base implementation class for extension installer. To be used inside a foreground [Service]. * Base implementation class for extension installer. To be used inside a foreground [Service].
*/ */
@OptIn(ExperimentalAtomicApi::class)
abstract class Installer(private val service: Service) { abstract class Installer(private val service: Service) {
private val extensionManager: ExtensionManager by injectLazy() private val extensionManager: ExtensionManager by injectLazy()
private var waitingInstall = AtomicReference<Entry>(null) private var waitingInstall = AtomicReference<Entry?>(null)
private val queue = Collections.synchronizedList(mutableListOf<Entry>()) private val queue = Collections.synchronizedList(mutableListOf<Entry>())
private val cancelReceiver = object : BroadcastReceiver() { private val cancelReceiver = object : BroadcastReceiver() {
@ -79,7 +81,7 @@ abstract class Installer(private val service: Service) {
* @see waitingInstall * @see waitingInstall
*/ */
fun continueQueue(resultStep: InstallStep) { fun continueQueue(resultStep: InstallStep) {
val completedEntry = waitingInstall.getAndSet(null) val completedEntry = waitingInstall.exchange(null)
if (completedEntry != null) { if (completedEntry != null) {
extensionManager.updateInstallStep(completedEntry.downloadId, resultStep) extensionManager.updateInstallStep(completedEntry.downloadId, resultStep)
checkQueue() checkQueue()
@ -115,10 +117,10 @@ abstract class Installer(private val service: Service) {
LocalBroadcastManager.getInstance(service).unregisterReceiver(cancelReceiver) LocalBroadcastManager.getInstance(service).unregisterReceiver(cancelReceiver)
queue.forEach { extensionManager.updateInstallStep(it.downloadId, InstallStep.Error) } queue.forEach { extensionManager.updateInstallStep(it.downloadId, InstallStep.Error) }
queue.clear() queue.clear()
waitingInstall.set(null) waitingInstall.store(null)
} }
protected fun getActiveEntry(): Entry? = waitingInstall.get() protected fun getActiveEntry(): Entry? = waitingInstall.load()
/** /**
* Cancels queue for the provided download ID if exists. * Cancels queue for the provided download ID if exists.
@ -126,13 +128,13 @@ abstract class Installer(private val service: Service) {
* @param downloadId Download ID as known by [ExtensionManager] * @param downloadId Download ID as known by [ExtensionManager]
*/ */
private fun cancelQueue(downloadId: Long) { private fun cancelQueue(downloadId: Long) {
val waitingInstall = this.waitingInstall.get() val waitingInstall = this.waitingInstall.load()
val toCancel = queue.find { it.downloadId == downloadId } ?: waitingInstall ?: return val toCancel = queue.find { it.downloadId == downloadId } ?: waitingInstall ?: return
if (cancelEntry(toCancel)) { if (cancelEntry(toCancel)) {
queue.remove(toCancel) queue.remove(toCancel)
if (waitingInstall == toCancel) { if (waitingInstall == toCancel) {
// Currently processing removed entry, continue queue // Currently processing removed entry, continue queue
this.waitingInstall.set(null) this.waitingInstall.store(null)
checkQueue() checkQueue()
} }
extensionManager.updateInstallStep(downloadId, InstallStep.Idle) extensionManager.updateInstallStep(downloadId, InstallStep.Idle)

View File

@ -26,7 +26,9 @@ import tachiyomi.core.common.util.lang.withIOContext
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.concurrent.PriorityBlockingQueue import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.concurrent.atomics.incrementAndFetch
import kotlin.math.min import kotlin.math.min
/** /**
@ -246,15 +248,16 @@ internal class HttpPageLoader(
/** /**
* Data class used to keep ordering of pages in order to maintain priority. * Data class used to keep ordering of pages in order to maintain priority.
*/ */
@OptIn(ExperimentalAtomicApi::class)
private class PriorityPage( private class PriorityPage(
val page: ReaderPage, val page: ReaderPage,
val priority: Int, val priority: Int,
) : Comparable<PriorityPage> { ) : Comparable<PriorityPage> {
companion object { companion object {
private val idGenerator = AtomicInteger() private val idGenerator = AtomicInt(0)
} }
private val identifier = idGenerator.incrementAndGet() private val identifier = idGenerator.incrementAndFetch()
override fun compareTo(other: PriorityPage): Int { override fun compareTo(other: PriorityPage): Int {
val p = other.priority.compareTo(priority) val p = other.priority.compareTo(priority)

View File

@ -16,20 +16,23 @@ import rx.Observable
import rx.Producer import rx.Producer
import rx.Subscription import rx.Subscription
import java.io.IOException import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean import kotlin.concurrent.atomics.AtomicBoolean
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.coroutines.resumeWithException import kotlin.coroutines.resumeWithException
val jsonMime = "application/json; charset=utf-8".toMediaType() val jsonMime = "application/json; charset=utf-8".toMediaType()
@OptIn(ExperimentalAtomicApi::class)
fun Call.asObservable(): Observable<Response> { fun Call.asObservable(): Observable<Response> {
return Observable.unsafeCreate { subscriber -> return Observable.unsafeCreate { subscriber ->
// Since Call is a one-shot type, clone it for each new subscriber. // Since Call is a one-shot type, clone it for each new subscriber.
val call = clone() val call = clone()
// Wrap the call in a helper which handles both unsubscription and backpressure. // Wrap the call in a helper which handles both unsubscription and backpressure.
val requestArbiter = object : AtomicBoolean(), Producer, Subscription { val requestArbiter = object : Producer, Subscription {
val boolean = AtomicBoolean(false)
override fun request(n: Long) { override fun request(n: Long) {
if (n == 0L || !compareAndSet(false, true)) return if (n == 0L || !boolean.compareAndSet(expectedValue = false, newValue = true)) return
try { try {
val response = call.execute() val response = call.execute()

View File

@ -7,7 +7,10 @@ import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.concurrent.RejectedExecutionException import java.util.concurrent.RejectedExecutionException
import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.atomics.AtomicInt
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlin.concurrent.atomics.decrementAndFetch
import kotlin.concurrent.atomics.incrementAndFetch
import kotlin.coroutines.ContinuationInterceptor import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
@ -127,6 +130,7 @@ private suspend fun CoroutineDispatcher.acquireTransactionThread(
/** /**
* A [CoroutineContext.Element] that indicates there is an on-going database transaction. * A [CoroutineContext.Element] that indicates there is an on-going database transaction.
*/ */
@OptIn(ExperimentalAtomicApi::class)
private class TransactionElement( private class TransactionElement(
private val transactionThreadControlJob: Job, private val transactionThreadControlJob: Job,
val transactionDispatcher: ContinuationInterceptor, val transactionDispatcher: ContinuationInterceptor,
@ -143,14 +147,14 @@ private class TransactionElement(
* when [release] is invoked then the transaction job is cancelled and the transaction thread * when [release] is invoked then the transaction job is cancelled and the transaction thread
* is released. * is released.
*/ */
private val referenceCount = AtomicInteger(0) private val referenceCount = AtomicInt(0)
fun acquire() { fun acquire() {
referenceCount.incrementAndGet() referenceCount.incrementAndFetch()
} }
fun release() { fun release() {
val count = referenceCount.decrementAndGet() val count = referenceCount.decrementAndFetch()
if (count < 0) { if (count < 0) {
throw IllegalStateException("Transaction was never started or was already released") throw IllegalStateException("Transaction was never started or was already released")
} else if (count == 0) { } else if (count == 0) {

View File

@ -1,5 +1,5 @@
[versions] [versions]
kotlin_version = "2.1.10" kotlin_version = "2.1.20"
serialization_version = "1.8.0" serialization_version = "1.8.0"
xml_serialization_version = "0.90.3" xml_serialization_version = "0.90.3"