Scheduler
Summary: Add a simple scheduler which operates in the following way. There are two type of tasks: main, background. The main task will run on the main thread whilst the background task will run on a background thread. The main task will be executing at a fixed internal whereas the background task will get queued on demand but can effectively consume what was produced by the main task at its own rate. Reviewed By: LukeDefeo Differential Revision: D38975283 fbshipit-source-id: 0633385d2938705a16f5fc75a28cad067e4a8e55
This commit is contained in:
committed by
Facebook GitHub Bot
parent
2e33febcde
commit
1b2f875cc6
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.uidebugger.scheduler
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.os.Looper
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
|
class Scheduler<T>(val task: Task<T>, val rate: Long = 500L) {
|
||||||
|
interface Task<T> {
|
||||||
|
fun execute(): T?
|
||||||
|
fun process(input: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mainLooper: Handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
private val mainRunnable = MainThreadRunnable()
|
||||||
|
private val backgroundRunnable = BackgroundThreadRunnable()
|
||||||
|
|
||||||
|
private var backgroundHandler: HandlerThread? = null
|
||||||
|
private var backgroundLooper: Handler? = null
|
||||||
|
|
||||||
|
private var isRunning = false
|
||||||
|
|
||||||
|
private val lock = ReentrantLock()
|
||||||
|
private val condition = lock.newCondition()
|
||||||
|
private val queue = mutableListOf<T>()
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
backgroundHandler = HandlerThread("INSPECTOR_WORKER")
|
||||||
|
backgroundHandler?.let { handlerThread ->
|
||||||
|
handlerThread.start()
|
||||||
|
backgroundLooper = Handler(handlerThread.looper)
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning = true
|
||||||
|
mainLooper.postDelayed(mainRunnable, rate)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
backgroundLooper?.post(CancellationRunnable())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun execute() {
|
||||||
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
|
mainRunnable.run()
|
||||||
|
} else {
|
||||||
|
mainLooper.post(mainRunnable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class MainThreadRunnable : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
if (!isRunning) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val output = task.execute()
|
||||||
|
output?.let { output ->
|
||||||
|
lock.withLock {
|
||||||
|
queue.add(output)
|
||||||
|
condition.signal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {}
|
||||||
|
|
||||||
|
mainLooper.postDelayed(mainRunnable, rate)
|
||||||
|
backgroundLooper?.post(backgroundRunnable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class BackgroundThreadRunnable : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
if (!isRunning) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var input: T?
|
||||||
|
lock.withLock {
|
||||||
|
while (queue.isEmpty()) {
|
||||||
|
condition.await()
|
||||||
|
}
|
||||||
|
input = queue.removeFirst()
|
||||||
|
}
|
||||||
|
input?.let { input -> task.process(input) }
|
||||||
|
} catch (e: Exception) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class CancellationRunnable : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
backgroundHandler?.interrupt()
|
||||||
|
|
||||||
|
mainLooper.removeCallbacks(mainRunnable)
|
||||||
|
backgroundLooper?.removeCallbacks(backgroundRunnable)
|
||||||
|
|
||||||
|
backgroundHandler = null
|
||||||
|
|
||||||
|
isRunning = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user