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

io.atlassian.util.concurrent.Executors Maven / Gradle / Ivy

Go to download

This project contains utility classes that are used by various products and projects inside Atlassian and may have some utility to the world at large.

The newest version!
package io.atlassian.util.concurrent;

import io.atlassian.util.concurrent.atomic.AtomicReference;

import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.function.Supplier;

import javax.annotation.Nonnull;

/**
 * Executors utility class.
 */
public final class Executors {
  /**
   * {@link java.util.concurrent.Executor} that limits the number submitted jobs
   * to a fixed upper bound, by blocking the producer thread on submission.
   *
   * @since 2.6.1
   * @see LimitedExecutor for implementation details.
   * @param delegate a {@link java.util.concurrent.Executor}.
   * @param limit a int.
   * @return a {@link java.util.concurrent.Executor}.
   */
  public static Executor limited(Executor delegate, int limit) {
    return new LimitedExecutor(delegate, limit);
  }

  /**
   * {@link java.util.concurrent.Executor} that limits the number submitted jobs
   * to a fixed upper bound, by blocking the producer thread on submission.
   *
   * @since 2.6.2
   * @see LimitedExecutor for implementation details.
   * @param delegate a {@link java.util.concurrent.Executor}.
   * @return a {@link io.atlassian.util.concurrent.ExecutorSubmitter}.
   */
  public static ExecutorSubmitter submitter(Executor delegate) {
    return new DefaultSubmitter(delegate);
  }

  static class DefaultSubmitter implements ExecutorSubmitter {
    private final Executor executor;

    DefaultSubmitter(final Executor executor) {
      this.executor = executor;
    }

    @Override public void execute(@Nonnull final Runnable command) {
      executor.execute(command);
    }

    @Override public  Promise submit(final Callable callable) {
      final CallableRunner runner = new CallableRunner(callable);
      executor.execute(runner);
      return runner.get();
    }

    @Override public  Promise submitSupplier(final Supplier supplier) {
      return submit(Suppliers.toCallable(supplier));
    }

    static class CallableRunner implements Runnable, Supplier> {

      enum State {
        WAITING, RUNNING, FINISHED
      }

      final Callable task;
      final Promises.SettablePromise promise = Promises.settablePromise();
      final AtomicReference state = new AtomicReference<>(State.WAITING);

      CallableRunner(Callable taskToRun) {
        task = taskToRun;
        promise.fail(t -> {
          if (promise.isCancelled()) {
            state.set(State.FINISHED);
          }
        });
      }

      @Override public void run() {
        if (state.compareAndSet(State.WAITING, State.RUNNING)) {
          try {
            final T value = task.call();
            if (state.compareAndSet(State.RUNNING, State.FINISHED)) {
              promise.set(value);
            }
          } catch (Exception ex) {
            if (state.compareAndSet(State.RUNNING, State.FINISHED)) {
              promise.exception(ex);
            }
          }
        }
      }

      @Override public Promise get() {
        return promise;
      }
    }

  }

  // /CLOVER:OFF
  private Executors() {
    throw new AssertionError("cannot instantiate!");
  }
  // /CLOVER:ON
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy