package org.eclipse.aether.util.concurrency;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import static java.util.Objects.requireNonNull;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

/**
 * A utility class to forward any uncaught {@link Error} or {@link RuntimeException} from a {@link Runnable} executed in
 * a worker thread back to the parent thread. The simplified usage pattern looks like this:
 * 
 * <pre>
 * RunnableErrorForwarder errorForwarder = new RunnableErrorForwarder();
 * for ( Runnable task : tasks )
 * {
 *     executor.execute( errorForwarder.wrap( task ) );
 * }
 * errorForwarder.await();
 * </pre>
 */
public final class RunnableErrorForwarder
{

    private final Thread thread = Thread.currentThread();

    private final AtomicInteger counter = new AtomicInteger();

    private final AtomicReference<Throwable> error = new AtomicReference<Throwable>();

    /**
     * Creates a new error forwarder for worker threads spawned by the current thread.
     */
    public RunnableErrorForwarder()
    {
    }

    /**
     * Wraps the specified runnable into an equivalent runnable that will allow forwarding of uncaught errors.
     *
     * @param runnable The runnable from which to forward errors, must not be {@code null}.
     * @return The error-forwarding runnable to eventually execute, never {@code null}.
     */
    public Runnable wrap( final Runnable runnable )
    {
        requireNonNull( runnable, "runnable cannot be null" );

        counter.incrementAndGet();

        return new Runnable()
        {
            public void run()
            {
                try
                {
                    runnable.run();
                }
                catch ( RuntimeException e )
                {
                    error.compareAndSet( null, e );
                    throw e;
                }
                catch ( Error e )
                {
                    error.compareAndSet( null, e );
                    throw e;
                }
                finally
                {
                    counter.decrementAndGet();
                    LockSupport.unpark( thread );
                }
            }
        };
    }

    /**
     * Causes the current thread to wait until all previously {@link #wrap(Runnable) wrapped} runnables have terminated
     * and potentially re-throws an uncaught {@link RuntimeException} or {@link Error} from any of the runnables. In
     * case multiple runnables encountered uncaught errors, one error is arbitrarily selected. <em>Note:</em> This
     * method must be called from the same thread that created this error forwarder instance.
     */
    public void await()
    {
        awaitTerminationOfAllRunnables();

        Throwable error = this.error.get();
        if ( error != null )
        {
            if ( error instanceof RuntimeException )
            {
                throw (RuntimeException) error;
            }
            else if ( error instanceof ThreadDeath )
            {
                throw new IllegalStateException( error );
            }
            else if ( error instanceof Error )
            {
                throw (Error) error;
            }
            throw new IllegalStateException( error );
        }
    }

    private void awaitTerminationOfAllRunnables()
    {
        if ( !thread.equals( Thread.currentThread() ) )
        {
            throw new IllegalStateException( "wrong caller thread, expected " + thread + " and not "
                + Thread.currentThread() );
        }

        boolean interrupted = false;

        while ( counter.get() > 0 )
        {
            LockSupport.park();

            if ( Thread.interrupted() )
            {
                interrupted = true;
            }
        }

        if ( interrupted )
        {
            Thread.currentThread().interrupt();
        }
    }

}
