001/*
002 * Java Genetic Algorithm Library (jenetics-8.1.0).
003 * Copyright (c) 2007-2024 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.util;
021
022import static java.util.Objects.requireNonNull;
023
024import java.util.concurrent.Executor;
025import java.util.concurrent.Executors;
026import java.util.concurrent.ForkJoinPool;
027
028/**
029 * Batch executor interface, which is used for evaluating a <em>batch</em> of
030 * runnables. The tasks of a batch are executed concurrently and the
031 * {@link #execute(BaseSeq)} method will return, if all tasks of the batch have
032 * been executed.
033 *
034 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
035 * @version 8.0
036 * @since 8.0
037 */
038@FunctionalInterface
039public interface BatchExecutor {
040
041        /**
042         * Executes the runnables of the {@code batch} concurrently and returns,
043         * when all tasks have been executed.
044         *
045         * @param batch the sequence of runnable to be executed concurrently
046         * @throws NullPointerException if the given {@code batch} is {@code null}
047         */
048        void execute(final BaseSeq<? extends Runnable> batch);
049
050        /**
051         * Create a batch executor, where the execution is forwarded to the given
052         * {@code executor}.
053         *
054         * @param executor the executor, which is actually executing the tasks
055         * @return a new batch executor
056         * @throws NullPointerException if the given {@code executor} is {@code null}
057         */
058        static BatchExecutor of(final Executor executor) {
059                requireNonNull(executor);
060
061                if (executor instanceof ForkJoinPool pool) {
062                        return new BatchForkJoinPool(pool);
063                } else {
064                        return new PartitionBatchExecutor(executor);
065                }
066        }
067
068        /**
069         * Return a batch executor, where each task of a given <em>batch</em> is
070         * executed in its own <em>virtual</em> thread.
071         *
072         * @return a new <em>virtual</em> thread batch executor object
073         */
074        static BatchExecutor ofVirtualThreads() {
075                return batch -> {
076                        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
077                                batch.forEach(executor::execute);
078                        }
079                };
080        }
081
082}