All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jbpm.util.Semaphore Maven / Gradle / Ivy

The newest version!
package org.jbpm.util;

import java.io.Serializable;

/**
 * A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each
 * {@linkplain #acquire acquire} blocks if necessary until a permit is available, and then takes it.
 * Each {@linkplain #release() release} adds a permit, potentially releasing a blocking acquirer.
 * 
 * @see java.util.concurrent.Semaphore
 */
public class Semaphore implements Serializable {

  private int permits;

  private static final long serialVersionUID = 1L;

  /**
   * Creates a Semaphore with the given number of permits.
   * 
   * @param permits the initial number of permits available. This value may be negative, in which
   *        case releases must occur before any acquires will be granted.
   */
  public Semaphore(int permits) {
    this.permits = permits;
  }

  /**
   * Releases a permit, returning it to the semaphore.
   */
  public void release() {
    release(1);
  }

  /**
   * Releases the given number of permits, returning them to the semaphore.
   * 
   * @param permits the number of permits to release
   * @throws IllegalArgumentException if permits less than zero.
   */
  public void release(int permits) {
    if (permits < 0) throw new IllegalArgumentException(Integer.toString(permits));

    synchronized (this) {
      this.permits += permits;
      notifyAll();
    }
  }

  /**
   * Acquires a permit from this semaphore, blocking until one is available, or the thread is
   * {@link Thread#interrupt interrupted}.
   * 
   * @throws InterruptedException if the current thread is interrupted
   * @see Thread#interrupt
   */
  public void acquire() throws InterruptedException {
    acquire(1);
  }

  /**
   * Acquires the given number of permits from this semaphore, blocking until all are available, or
   * the thread is {@link Thread#interrupt interrupted}.
   * 
   * @param permits the number of permits to acquire
   * @throws InterruptedException if the current thread is interrupted
   * @throws IllegalArgumentException if permits less than zero.
   * @see Thread#interrupt
   */
  public void acquire(int permits) throws InterruptedException {
    if (permits < 0) throw new IllegalArgumentException(Integer.toString(permits));

    synchronized (this) {
      while (this.permits < permits) {
        wait();
      }
      this.permits -= permits;
    }
  }

  /**
   * Acquires a permit from this semaphore, if one becomes available within the given waiting time
   * and the current thread has not been {@link Thread#interrupt interrupted}.
   * 
   * @param timeout the maximum time to wait for a permit
   * @return true if a permit was acquired and false if the waiting time elapsed
   *         before a permit was acquired.
   * @throws InterruptedException if the current thread is interrupted
   * @see Thread#interrupt
   */
  public boolean tryAcquire(long timeout) throws InterruptedException {
    return tryAcquire(1, timeout);
  }

  /**
   * Acquires the given number of permits from this semaphore, if all become available within the
   * given waiting time and the current thread has not been {@link Thread#interrupt interrupted}.
   * 
   * @param permits the number of permits to acquire
   * @param timeout the maximum time to wait for the permits
   * @return true if all permits were acquired and false if the waiting time
   *         elapsed before all permits were acquired.
   * @throws InterruptedException if the current thread is interrupted
   * @throws IllegalArgumentException if permits less than zero.
   * @see Thread#interrupt
   */
  public boolean tryAcquire(int permits, long timeout) throws InterruptedException {
    if (permits < 0) {
    	throw new IllegalArgumentException(Integer.toString(permits));
    }

    long timeoutNano = timeout * 1000000L;
    long startTimeNano = System.nanoTime();
    synchronized (this) {
      while (this.permits < permits) {
        if (System.nanoTime() - startTimeNano >= timeoutNano) {
        	return false;
        }
        wait(timeout);
      }
      this.permits -= permits;
      return true;
    }
  }

  /**
   * Acquire and return all permits that are immediately available.
   * 
   * @return the number of permits
   */
  public synchronized int drainPermits() {
    int permits = this.permits;
    this.permits = 0;
    return permits;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy