public class

ConditionVariable

extends java.lang.Object

 java.lang.Object

↳androidx.media3.common.util.ConditionVariable

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

An interruptible condition variable. This class provides a number of benefits over :

Summary

Constructors
publicConditionVariable()

Creates an instance using Clock.DEFAULT.

publicConditionVariable(Clock clock)

Creates an instance, which starts closed.

Methods
public synchronized voidblock()

Blocks until the condition is opened.

public synchronized booleanblock(long timeoutMs)

Blocks until the condition is opened or until timeoutMs have passed.

public synchronized voidblockUninterruptible()

Blocks until the condition is open.

public synchronized booleanclose()

Closes the condition.

public synchronized booleanisOpen()

Returns whether the condition is opened.

public synchronized booleanopen()

Opens the condition and releases all threads that are blocked.

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

Constructors

public ConditionVariable()

Creates an instance using Clock.DEFAULT.

public ConditionVariable(Clock clock)

Creates an instance, which starts closed.

Parameters:

clock: The Clock whose Clock.elapsedRealtime() method is used to determine when ConditionVariable.block(long) should time out.

Methods

public synchronized boolean open()

Opens the condition and releases all threads that are blocked.

Returns:

True if the condition variable was opened. False if it was already open.

public synchronized boolean close()

Closes the condition.

Returns:

True if the condition variable was closed. False if it was already closed.

public synchronized void block()

Blocks until the condition is opened.

public synchronized boolean block(long timeoutMs)

Blocks until the condition is opened or until timeoutMs have passed.

Parameters:

timeoutMs: The maximum time to wait in milliseconds. If timeoutMs <= 0 then the call will return immediately without blocking.

Returns:

True if the condition was opened, false if the call returns because of the timeout.

public synchronized void blockUninterruptible()

Blocks until the condition is open. Unlike ConditionVariable.block(), this method will continue to block if the calling thread is interrupted. If the calling thread was interrupted then its interrupted status will be set when the method returns.

public synchronized boolean isOpen()

Returns whether the condition is opened.

Source

/*
 * Copyright (C) 2016 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;

/**
 * An interruptible condition variable. This class provides a number of benefits over {@link
 * android.os.ConditionVariable}:
 *
 * <ul>
 *   <li>Consistent use of ({@link Clock#elapsedRealtime()} for timing {@link #block(long)} timeout
 *       intervals. {@link android.os.ConditionVariable} used {@link System#currentTimeMillis()}
 *       prior to Android 10, which is not a correct clock to use for interval timing because it's
 *       not guaranteed to be monotonic.
 *   <li>Support for injecting a custom {@link Clock}.
 *   <li>The ability to query the variable's current state, by calling {@link #isOpen()}.
 *   <li>{@link #open()} and {@link #close()} return whether they changed the variable's state.
 * </ul>
 */
@UnstableApi
public class ConditionVariable {

  private final Clock clock;
  private boolean isOpen;

  /** Creates an instance using {@link Clock#DEFAULT}. */
  public ConditionVariable() {
    this(Clock.DEFAULT);
  }

  /**
   * Creates an instance, which starts closed.
   *
   * @param clock The {@link Clock} whose {@link Clock#elapsedRealtime()} method is used to
   *     determine when {@link #block(long)} should time out.
   */
  public ConditionVariable(Clock clock) {
    this.clock = clock;
  }

  /**
   * Opens the condition and releases all threads that are blocked.
   *
   * @return True if the condition variable was opened. False if it was already open.
   */
  public synchronized boolean open() {
    if (isOpen) {
      return false;
    }
    isOpen = true;
    notifyAll();
    return true;
  }

  /**
   * Closes the condition.
   *
   * @return True if the condition variable was closed. False if it was already closed.
   */
  public synchronized boolean close() {
    boolean wasOpen = isOpen;
    isOpen = false;
    return wasOpen;
  }

  /**
   * Blocks until the condition is opened.
   *
   * @throws InterruptedException If the thread is interrupted.
   */
  public synchronized void block() throws InterruptedException {
    while (!isOpen) {
      wait();
    }
  }

  /**
   * Blocks until the condition is opened or until {@code timeoutMs} have passed.
   *
   * @param timeoutMs The maximum time to wait in milliseconds. If {@code timeoutMs <= 0} then the
   *     call will return immediately without blocking.
   * @return True if the condition was opened, false if the call returns because of the timeout.
   * @throws InterruptedException If the thread is interrupted.
   */
  public synchronized boolean block(long timeoutMs) throws InterruptedException {
    if (timeoutMs <= 0) {
      return isOpen;
    }
    long nowMs = clock.elapsedRealtime();
    long endMs = nowMs + timeoutMs;
    if (endMs < nowMs) {
      // timeoutMs is large enough for (nowMs + timeoutMs) to rollover. Block indefinitely.
      block();
    } else {
      while (!isOpen && nowMs < endMs) {
        wait(endMs - nowMs);
        nowMs = clock.elapsedRealtime();
      }
    }
    return isOpen;
  }

  /**
   * Blocks until the condition is open. Unlike {@link #block}, this method will continue to block
   * if the calling thread is interrupted. If the calling thread was interrupted then its {@link
   * Thread#isInterrupted() interrupted status} will be set when the method returns.
   */
  public synchronized void blockUninterruptible() {
    boolean wasInterrupted = false;
    while (!isOpen) {
      try {
        wait();
      } catch (InterruptedException e) {
        wasInterrupted = true;
      }
    }
    if (wasInterrupted) {
      // Restore the interrupted status.
      Thread.currentThread().interrupt();
    }
  }

  /** Returns whether the condition is opened. */
  public synchronized boolean isOpen() {
    return isOpen;
  }
}