001package com.mrivanplays.process;
002
003import java.util.Map;
004import java.util.concurrent.ConcurrentHashMap;
005import java.util.concurrent.CountDownLatch;
006import java.util.concurrent.Executor;
007import java.util.function.Consumer;
008
009/**
010 * Represents a completion of all the {@link ResultedProcess resulted processes}
011 *
012 * @param <T> result type parameter
013 * @author <a href="mailto:[email protected]">Ivan Pekov</a>
014 * @since 0.0.1
015 */
016public final class ResultedProcessesCompletion<T> {
017
018  /**
019   * Called when all {@link ResultedProcess Proccesses} are done.
020   * <p><b>WARNING: THREAD BLOCKING METHOD.</b>
021   *
022   * @param callback a {@link Consumer} of the results
023   */
024  public void whenDone(Consumer<Map<String, ProcessResult<T>>> callback) {
025    if (this.latch.getCount() == 0) {
026      callback.accept(this.resultMap);
027      return;
028    }
029    try {
030      this.latch.await();
031      callback.accept(this.resultMap);
032    } catch (InterruptedException e) {
033      Thread.currentThread().interrupt();
034    }
035  }
036
037  /**
038   * Called when all {@link ResultedProcess Processes} are done. The difference from {@link
039   * #whenDone(Consumer)} is that the waiting and the {@code callback} call is done asynchronously.
040   *
041   * @param callback a {@link Consumer} of the results.
042   * @see #whenDone(Consumer)
043   */
044  public void whenDoneAsync(Consumer<Map<String, ProcessResult<T>>> callback) {
045    this.asyncExecutor.execute(() -> this.whenDone(callback));
046  }
047
048  // ======================================
049
050  private final CountDownLatch latch;
051  private final Executor asyncExecutor;
052  private Map<String, ProcessResult<T>> resultMap;
053
054  ResultedProcessesCompletion(int processCount, Executor asyncExecutor) {
055    this.latch = new CountDownLatch(processCount);
056    this.asyncExecutor = asyncExecutor;
057    this.resultMap = new ConcurrentHashMap<>();
058  }
059
060  void countDown(String identifier, ProcessResult<T> result) {
061    this.resultMap.put(identifier, result);
062    this.latch.countDown();
063  }
064}