Fix and Refactor both RepoManager and BackgroundUpdateChecker
parent
23c153a6ed
commit
248865d617
@ -0,0 +1,73 @@
|
||||
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;
|
||||
|
||||
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) {
|
||||
this.syncing = true;
|
||||
try {
|
||||
this.scanInternal(updateListener);
|
||||
} finally {
|
||||
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 boolean isRepoUpdating() {
|
||||
return this.syncing;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue