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

org.opentcs.common.SameThreadExecutorService Maven / Gradle / Ivy

The newest version!
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.common;

import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkArgument;
import static org.opentcs.util.Assertions.checkState;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

/**
 * An executor service that executes all task directly on the same thread.
 */
public class SameThreadExecutorService
    implements
      ExecutorService {

  private boolean shutdown;

  public SameThreadExecutorService() {
    shutdown = false;
  }

  @Override
  public void shutdown() {
    shutdown = true;
  }

  @Override
  public List shutdownNow() {
    shutdown = true;
    return List.of();
  }

  @Override
  public boolean isShutdown() {
    return shutdown;
  }

  @Override
  public boolean isTerminated() {
    return shutdown;
  }

  @Override
  public boolean awaitTermination(long timeout, TimeUnit unit)
      throws InterruptedException {
    // Calling `awaitTermination` before calling shutdown is not a valid use for an executor
    // service and therefore should throw an exeception.
    checkState(shutdown, "Awaiting termination before shutdown was called");
    return true;
  }

  @Override
  public  Future submit(Callable task) {
    CompletableFuture future = new CompletableFuture<>();
    try {
      future.complete(task.call());
    }
    catch (Exception e) {
      future.completeExceptionally(e);
    }
    return future;
  }

  @Override
  public  Future submit(Runnable task, T result) {
    return this.submit(() -> {
      task.run();
      return result;
    });
  }

  @Override
  public Future submit(Runnable task) {
    return this.submit(task, null);
  }

  @Override
  public  List> invokeAll(Collection> tasks)
      throws InterruptedException {
    return tasks.stream()
        .map(task -> submit(task))
        .collect(Collectors.toList());
  }

  @Override
  public  List> invokeAll(
      Collection> tasks,
      long timeout,
      TimeUnit unit
  )
      throws InterruptedException {
    return invokeAll(tasks);
  }

  @Override
  public  T invokeAny(Collection> tasks)
      throws InterruptedException,
        ExecutionException {
    requireNonNull(tasks, "tasks");
    checkArgument(tasks.isEmpty(), "tasks is empty");
    if (tasks.stream().anyMatch(task -> task == null)) {
      throw new NullPointerException("At least one task given is null");
    }

    // This implementation interprets the method documentation so that all tasks are started
    // before the result of the first successful one is returned.
    // Since all task are executed directly on the same thread, all task will finish before this
    // method returns the value of any successful task.
    List> futures = invokeAll(tasks);

    for (Future future : futures) {
      try {
        return future.get();
      }
      catch (InterruptedException e) {
        throw e;
      }
      catch (Exception e) {
        // any other exception thrown by the future is ignored
      }
    }

    throw new ExecutionException(new Exception("None of the provided task sucessfully terminated"));
  }

  @Override
  public  T invokeAny(Collection> tasks, long timeout, TimeUnit unit)
      throws InterruptedException,
        ExecutionException,
        TimeoutException {
    return invokeAny(tasks);
  }

  @Override
  public void execute(Runnable command) {
    command.run();
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy