Revert "Reapply "Fix thread starvation caused by not yielding or using an inappropriate thread pool (#2955)""

This reverts commit 9c01119d24.

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt
This commit is contained in:
Jobobby04
2026-04-08 15:02:37 -04:00
parent 170358f88e
commit 509ace1a38
16 changed files with 125 additions and 209 deletions
@@ -5,8 +5,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.util.concurrent.RejectedExecutionException
import kotlin.concurrent.atomics.AtomicInt
@@ -19,10 +17,6 @@ import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.coroutineContext
import kotlin.coroutines.resume
// Global mutex to serialize transaction entry and prevent thread pool exhaustion.
// If you have multiple distinct database files/handlers, this should be a property of AndroidDatabaseHandler.
private val transactionMutex = Mutex()
/**
* Returns the transaction dispatcher if we are on a transaction, or the database dispatchers.
*/
@@ -45,41 +39,20 @@ internal suspend fun AndroidDatabaseHandler.getCurrentDatabaseContext(): Corouti
* The dispatcher used to execute the given [block] will utilize threads from SQLDelight's query executor.
*/
internal suspend fun <T> AndroidDatabaseHandler.withTransaction(block: suspend () -> T): T {
val transactionElement = coroutineContext[TransactionElement]
// If we are already in a transaction, we don't need to lock the Mutex.
// We just reuse the existing thread/context.
if (transactionElement != null) {
return withContext(transactionElement.transactionDispatcher) {
transactionElement.acquire()
try {
db.transactionWithResult {
runBlocking(transactionElement.transactionDispatcher) {
block()
}
// Use inherited transaction context if available, this allows nested suspending transactions.
val transactionContext =
coroutineContext[TransactionElement]?.transactionDispatcher ?: createTransactionContext()
return withContext(transactionContext) {
val transactionElement = coroutineContext[TransactionElement]!!
transactionElement.acquire()
try {
db.transactionWithResult {
runBlocking(transactionContext) {
block()
}
} finally {
transactionElement.release()
}
}
}
// transaction: Acquire Mutex BEFORE acquiring a thread.
// This ensures we only block a real thread when we have exclusive access.
return transactionMutex.withLock {
val transactionContext = createTransactionContext()
withContext(transactionContext) {
val element = coroutineContext[TransactionElement]!!
element.acquire()
try {
db.transactionWithResult {
runBlocking(transactionContext) {
block()
}
}
} finally {
element.release()
}
} finally {
transactionElement.release()
}
}
}