001/*
002 * Java Genetic Algorithm Library (jenetics-8.0.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.internal.util;
021
022import java.util.Iterator;
023import java.util.concurrent.CancellationException;
024import java.util.concurrent.CompletionException;
025import java.util.concurrent.ExecutionException;
026import java.util.concurrent.Future;
027
028/**
029 * Helper method for handĺing future objects.
030 *
031 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
032 * @version 8.0
033 * @since 8.0
034 */
035public final class Futures {
036        private Futures() {
037        }
038
039        /**
040         * Joins the given set of futures.
041         *
042         * @param futures the future objects to join.
043         */
044        public static void join(final Iterable<? extends Future<?>> futures) {
045                final Iterator<? extends Future<?>> tasks = futures.iterator();
046
047                Exception exception = null;
048                Future<?> future = null;
049                try {
050                        while (tasks.hasNext()) {
051                                future = tasks.next();
052                                future.get();
053                        }
054                        future = null;
055                } catch (InterruptedException |
056                         ExecutionException |
057                         CancellationException e)
058                {
059                        exception = e;
060                }
061
062                // Cancel all remaining tasks, in case of an error.
063                if (future != null) {
064                        future.cancel(true);
065                        tasks.forEachRemaining(t -> t.cancel(true));
066                }
067
068                // Handle exceptions, if any.
069                if (exception instanceof InterruptedException ie) {
070                        Thread.currentThread().interrupt();
071                        final var ce = new CancellationException(ie.getMessage());
072                        ce.initCause(ie);
073                        throw ce;
074                } else if (exception instanceof CancellationException e) {
075                        throw e;
076                } else if (exception != null) {
077                        throw new CompletionException(exception);
078                }
079        }
080
081}