package com.artemzin.qualitymatters.performance;
import android.support.annotation.NonNull;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Collections.newSetFromMap;
public class AsyncJobsObserverImpl implements AsyncJobsObserver {
@NonNull
@AnyThread
private final AtomicInteger asyncJobsIdGenerator = new AtomicInteger(0);
@NonNull
@AnyThread
private final Set<AsyncJob> asyncJobs = newSetFromMap(new ConcurrentHashMap<>());
@NonNull
@AnyThread
private final Queue<Listener> listeners = new ConcurrentLinkedQueue<>();
@AnyThread
@Override
public void addListener(@NonNull Listener listener) {
listeners.add(listener);
}
@AnyThread
@Override
public void removeListener(@NonNull Listener listener) {
final boolean removed = listeners.remove(listener);
if (!removed) {
throw new IllegalArgumentException("Listener was not registered!");
}
}
@AnyThread
@Override
public int numberOfRunningAsyncJobs() {
return asyncJobs.size();
}
@AnyThread
@NonNull
@Override
public AsyncJob asyncJobStarted(@NonNull String name) {
AsyncJob asyncJob = AsyncJob.create(asyncJobsIdGenerator.getAndIncrement(), name);
asyncJobs.add(asyncJob);
notifyListenersAboutChangedNumberOfRunningAsyncJobs();
return asyncJob;
}
@AnyThread
@Override
public void asyncJobFinished(@NonNull AsyncJob asyncJob) {
final boolean removed = asyncJobs.remove(asyncJob);
if (!removed) {
throw new IllegalArgumentException("Async job was not registered in the AsyncJobsObserver! Job: " + asyncJob);
}
notifyListenersAboutChangedNumberOfRunningAsyncJobs();
}
private void notifyListenersAboutChangedNumberOfRunningAsyncJobs() {
// This is not super consistent since we don't want to do synchronization, but it's okay for us in this case.
final int numberOfRunningAsyncJobs = numberOfRunningAsyncJobs();
for (Listener listener : listeners) {
listener.onNumberOfRunningAsyncJobsChanged(numberOfRunningAsyncJobs);
}
}
}