package org.infinispan.util.concurrent.jdk8backported;

/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

/**
 * A thread managed by a {@link ForkJoinPool}, which executes
 * {@link ForkJoinTask}s.
 * This class is subclassable solely for the sake of adding
 * functionality -- there are no overridable methods dealing with
 * scheduling or execution.  However, you can override initialization
 * and termination methods surrounding the main task processing loop.
 * If you do create such a subclass, you will also need to supply a
 * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it
 * in a {@code ForkJoinPool}.
 *
 * @since 1.7
 * @author Doug Lea
 */
public class ForkJoinWorkerThread extends Thread {
   /*
   * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
   * ForkJoinTasks. For explanation, see the internal documentation
   * of class ForkJoinPool.
   */

   final ForkJoinPool.WorkQueue workQueue; // Work-stealing mechanics
   final ForkJoinPool pool;                // the pool this thread works in

   /**
    * Creates a ForkJoinWorkerThread operating in the given pool.
    *
    * @param pool the pool this thread works in
    * @throws NullPointerException if pool is null
    */
   protected ForkJoinWorkerThread(ForkJoinPool pool) {
      super(pool.nextWorkerName());
      setDaemon(true);
      Thread.UncaughtExceptionHandler ueh = pool.ueh;
      if (ueh != null)
         setUncaughtExceptionHandler(ueh);
      this.pool = pool;
      pool.registerWorker(this.workQueue = new ForkJoinPool.WorkQueue
            (pool, this, pool.localMode));
   }

   /**
    * Returns the pool hosting this thread.
    *
    * @return the pool
    */
   public ForkJoinPool getPool() {
      return pool;
   }

   /**
    * Returns the index number of this thread in its pool.  The
    * returned value ranges from zero to the maximum number of
    * threads (minus one) that have ever been created in the pool.
    * This method may be useful for applications that track status or
    * collect results per-worker rather than per-task.
    *
    * @return the index number
    */
   public int getPoolIndex() {
      return workQueue.poolIndex;
   }

   /**
    * Initializes internal state after construction but before
    * processing any tasks. If you override this method, you must
    * invoke {@code super.onStart()} at the beginning of the method.
    * Initialization requires care: Most fields must have legal
    * default values, to ensure that attempted accesses from other
    * threads work correctly even before this thread starts
    * processing tasks.
    */
   protected void onStart() {
   }

   /**
    * Performs cleanup associated with termination of this worker
    * thread.  If you override this method, you must invoke
    * {@code super.onTermination} at the end of the overridden method.
    *
    * @param exception the exception causing this thread to abort due
    * to an unrecoverable error, or {@code null} if completed normally
    */
   protected void onTermination(Throwable exception) {
   }

   /**
    * This method is required to be public, but should never be
    * called explicitly. It performs the main run loop to execute
    * {@link ForkJoinTask}s.
    */
   public void run() {
      Throwable exception = null;
      try {
         onStart();
         pool.runWorker(workQueue);
      } catch (Throwable ex) {
         exception = ex;
      } finally {
         try {
            onTermination(exception);
         } catch (Throwable ex) {
            if (exception == null)
               exception = ex;
         } finally {
            pool.deregisterWorker(this, exception);
         }
      }
   }
}