class CaptureObjectLoader {

  @NotNull
  public ListenableFuture<CaptureObject> loadCapture(@NotNull CaptureObject captureObject,
                                                     @Nullable Range queryRange,
                                                     @Nullable Executor queryJoiner) {
    assert myExecutorService != null;
    cancelTask();

    ListenableFutureTask<CaptureObject> task =
      ListenableFutureTask.create(() -> captureObject.load(queryRange, queryJoiner) ? captureObject : null);
    myOutstandingLoadingTask = task;

    Futures.addCallback(task, new FutureCallback<CaptureObject>() {
      @Override
      public void onSuccess(@Nullable CaptureObject result) {
        removeTask();
      }

      @Override
      public void onFailure(@NotNull Throwable ignored) {
        removeTask();
      }

      private void removeTask() {
        myOutstandingLoadingTask = null;
      }
    }, MoreExecutors.directExecutor());

    myExecutorService.execute(task);
    return task;
  }

}