public abstract class

RunnableFutureTask<R, E extends java.lang.Exception>

extends java.lang.Object

implements java.util.concurrent.RunnableFuture<java.lang.Object>

 java.lang.Object

↳androidx.media3.common.util.RunnableFutureTask<R, E>

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-common', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-common
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-common:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

A java.util.concurrent.RunnableFuture that supports additional uninterruptible operations to query whether execution has started and finished.

Summary

Constructors
protectedRunnableFutureTask()

Methods
public final voidblockUntilFinished()

Blocks until the task has finished, or has been canceled without having been started.

public final voidblockUntilStarted()

Blocks until the task has started, or has been canceled without having been started.

public final booleancancel(boolean interruptIfRunning)

protected voidcancelWork()

Cancels any work being done by RunnableFutureTask.doWork().

protected abstract java.lang.ObjectdoWork()

Performs the work or computation.

public final java.lang.Objectget()

public final java.lang.Objectget(long timeout, java.util.concurrent.TimeUnit unit)

public final booleanisCancelled()

public final booleanisDone()

public final voidrun()

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

protected RunnableFutureTask()

Methods

public final void blockUntilStarted()

Blocks until the task has started, or has been canceled without having been started.

public final void blockUntilFinished()

Blocks until the task has finished, or has been canceled without having been started.

public final java.lang.Object get()

public final java.lang.Object get(long timeout, java.util.concurrent.TimeUnit unit)

public final boolean cancel(boolean interruptIfRunning)

public final boolean isDone()

public final boolean isCancelled()

public final void run()

protected abstract java.lang.Object doWork()

Performs the work or computation.

Returns:

The computed result.

protected void cancelWork()

Cancels any work being done by RunnableFutureTask.doWork(). If RunnableFutureTask.doWork() is currently executing then the thread on which it's executing may be interrupted immediately after this method returns.

The default implementation does nothing.

Source

/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.media3.common.util;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

import androidx.annotation.Nullable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * A {@link RunnableFuture} that supports additional uninterruptible operations to query whether
 * execution has started and finished.
 *
 * @param <R> The type of the result.
 * @param <E> The type of any {@link ExecutionException} cause.
 */
@UnstableApi
public abstract class RunnableFutureTask<R, E extends Exception> implements RunnableFuture<R> {

  private final ConditionVariable started;
  private final ConditionVariable finished;
  private final Object cancelLock;

  @Nullable private Exception exception;
  @Nullable private R result;

  @Nullable private Thread workThread;
  private boolean canceled;

  protected RunnableFutureTask() {
    started = new ConditionVariable();
    finished = new ConditionVariable();
    cancelLock = new Object();
  }

  /** Blocks until the task has started, or has been canceled without having been started. */
  public final void blockUntilStarted() {
    started.blockUninterruptible();
  }

  /** Blocks until the task has finished, or has been canceled without having been started. */
  public final void blockUntilFinished() {
    finished.blockUninterruptible();
  }

  // Future implementation.

  @Override
  @UnknownNull
  public final R get() throws ExecutionException, InterruptedException {
    finished.block();
    return getResult();
  }

  @Override
  @UnknownNull
  public final R get(long timeout, TimeUnit unit)
      throws ExecutionException, InterruptedException, TimeoutException {
    long timeoutMs = MILLISECONDS.convert(timeout, unit);
    if (!finished.block(timeoutMs)) {
      throw new TimeoutException();
    }
    return getResult();
  }

  @Override
  public final boolean cancel(boolean interruptIfRunning) {
    synchronized (cancelLock) {
      if (canceled || finished.isOpen()) {
        return false;
      }
      canceled = true;
      cancelWork();
      @Nullable Thread workThread = this.workThread;
      if (workThread != null) {
        if (interruptIfRunning) {
          workThread.interrupt();
        }
      } else {
        started.open();
        finished.open();
      }
      return true;
    }
  }

  @Override
  public final boolean isDone() {
    return finished.isOpen();
  }

  @Override
  public final boolean isCancelled() {
    return canceled;
  }

  // Runnable implementation.

  @Override
  public final void run() {
    synchronized (cancelLock) {
      if (canceled) {
        return;
      }
      workThread = Thread.currentThread();
    }
    started.open();
    try {
      result = doWork();
    } catch (Exception e) {
      // Must be an instance of E or RuntimeException.
      exception = e;
    } finally {
      synchronized (cancelLock) {
        finished.open();
        workThread = null;
        // Clear the interrupted flag if set, to avoid it leaking into any subsequent tasks executed
        // using the calling thread.
        Thread.interrupted();
      }
    }
  }

  // Internal methods.

  /**
   * Performs the work or computation.
   *
   * @return The computed result.
   * @throws E If an error occurred.
   */
  @UnknownNull
  protected abstract R doWork() throws E;

  /**
   * Cancels any work being done by {@link #doWork()}. If {@link #doWork()} is currently executing
   * then the thread on which it's executing may be interrupted immediately after this method
   * returns.
   *
   * <p>The default implementation does nothing.
   */
  protected void cancelWork() {
    // Do nothing.
  }

  // The return value is guaranteed to be non-null if and only if R is a non-null type, but there's
  // no way to assert this. Suppress the warning instead.
  @SuppressWarnings("nullness:return")
  @UnknownNull
  private R getResult() throws ExecutionException {
    if (canceled) {
      throw new CancellationException();
    } else if (exception != null) {
      throw new ExecutionException(exception);
    }
    return result;
  }
}