58 lines
1.9 KiB
Kotlin
58 lines
1.9 KiB
Kotlin
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.fenix.utils
|
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
import java.util.concurrent.atomic.AtomicBoolean
|
|
|
|
/**
|
|
* A queue that acts as a gate, either executing tasks right away if the queue is marked as "ready",
|
|
* i.e. gate is open, or queues them to be executed whenever the queue is marked as ready in the
|
|
* future, i.e. gate becomes open.
|
|
*/
|
|
class RunWhenReadyQueue {
|
|
private val tasks = CopyOnWriteArrayList<() -> Unit>()
|
|
private val isReady = AtomicBoolean(false)
|
|
|
|
/**
|
|
* Was this queue ever marked as 'ready' via a call to [ready]?
|
|
*
|
|
* @return Boolean value indicating if this queue is 'ready'.
|
|
*/
|
|
fun isReady(): Boolean = isReady.get()
|
|
|
|
/**
|
|
* Runs the [task] if this queue is marked as ready, or queues it for later execution.
|
|
* Task will be executed on the main thread.
|
|
*
|
|
* @param task: The task to run now if queue is ready or queue for later execution.
|
|
*/
|
|
fun runIfReadyOrQueue(task: () -> Unit) {
|
|
if (isReady.get()) {
|
|
CoroutineScope(Dispatchers.Main).launch { task.invoke() }
|
|
} else {
|
|
tasks.add(task)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mark queue as ready. Pending tasks will execute, and all tasks passed to [runIfReadyOrQueue]
|
|
* after this point will be executed immediately.
|
|
*/
|
|
fun ready() {
|
|
// Make sure that calls to `ready` are idempotent.
|
|
if (!isReady.compareAndSet(false, true)) {
|
|
return
|
|
}
|
|
|
|
CoroutineScope(Dispatchers.Main).launch {
|
|
tasks.forEach { it.invoke() }.also { tasks.clear() }
|
|
}
|
|
}
|
|
}
|