blob: b13ec7e3412af677c9b089eda13073a024f01a6c [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.googlesignin;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* A class for running tasks in a background thread.
*
* <p>TODO(jackson): If this class is useful for other plugins, consider including it in a shared
* library or in the Flutter engine
*/
public final class BackgroundTaskRunner {
/**
* Interface that callers of this API can implement to be notified when a {@link
* #runInBackground(Callable,Callback) background task} has completed.
*/
public interface Callback<T> {
/**
* Invoked on the UI thread when the specified future has completed (calling {@code get()} on
* the future is guaranteed not to block). If the future completed with an exception, then
* {@code get()} will throw an {@code ExecutionException}.
*/
void run(Future<T> future);
}
private final ThreadPoolExecutor executor;
/**
* Creates a new background processor with the given number of threads.
*
* @param threads The fixed number of threads in ther pool.
*/
public BackgroundTaskRunner(int threads) {
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
// Only keeps idle threads open for 1 second if we've got more threads than cores.
executor = new ThreadPoolExecutor(threads, threads, 1, TimeUnit.SECONDS, workQueue);
}
/**
* Executes the specified task in a background thread and notifies the specified callback once the
* task has completed (either successfully or with an exception).
*
* <p>The callback will be notified on the UI thread.
*/
public <T> void runInBackground(Callable<T> task, final Callback<T> callback) {
final ListenableFuture<T> future = runInBackground(task);
future.addListener(
new Runnable() {
@Override
public void run() {
callback.run(future);
}
},
Executors.uiThreadExecutor());
}
/**
* Executes the specified task in a background thread and returns a future with which the caller
* can be notified of task completion.
*
* <p>Note: the future will be notified on the background thread. To be notified on the UI thread,
* use {@link #runInBackground(Callable,Callback)}.
*/
public <T> ListenableFuture<T> runInBackground(final Callable<T> task) {
final SettableFuture<T> future = SettableFuture.create();
executor.execute(
new Runnable() {
@Override
public void run() {
if (!future.isCancelled()) {
try {
future.set(task.call());
} catch (Throwable t) {
future.setException(t);
}
}
}
});
return future;
}
}