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:
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user