You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FoxMagiskModuleManager/app/src/main/java/com/fox2code/mmm/utils/SyncManager.java

80 lines
2.4 KiB
Java

package com.fox2code.mmm.utils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* Manager that want both to be thread safe and not to worry about thread safety
* {@link #scan()} and {@link #update(UpdateListener)} can be called from multiple
* thread at the same time, {@link #scanInternal(UpdateListener)} will only be
* called from one thread at a time only.
*/
public abstract class SyncManager {
private static final UpdateListener NO_OP = value -> {};
protected final Object syncLock = new Object();
private boolean syncing;
private long lastSync;
public final void scanAsync() {
if (!this.syncing) {
new Thread(this::scan, "Scan Thread").start();
}
}
public final void scan() {
this.update(null);
}
// MultiThread friendly method
public final void update(@Nullable UpdateListener updateListener) {
if (updateListener == null) updateListener = NO_OP;
if (!this.syncing) {
// Do scan
synchronized (this.syncLock) {
if (System.currentTimeMillis() < this.lastSync + 50L)
return; // Skip sync if it was synced too recently
this.syncing = true;
try {
this.scanInternal(updateListener);
} finally {
this.lastSync = System.currentTimeMillis();
this.syncing = false;
}
}
} else {
// Wait for current scan
synchronized (this.syncLock) {
Thread.yield();
}
}
}
// Pause execution until the scan is completed if one is currently running
public final void afterScan() {
if (this.syncing) synchronized (this.syncLock) { Thread.yield(); }
}
public final void runAfterScan(Runnable runnable) {
synchronized (this.syncLock) {
runnable.run();
}
}
public final void afterUpdate() {
if (this.syncing) synchronized (this.syncLock) { Thread.yield(); }
}
public final void runAfterUpdate(Runnable runnable) {
synchronized (this.syncLock) {
runnable.run();
}
}
// This method can't be called twice at the same time.
protected abstract void scanInternal(@NonNull UpdateListener updateListener);
public interface UpdateListener {
void update(double value);
}
}