package nxm.sys.lib;

import java.util.concurrent.atomic.AtomicInteger;

/**
  Thread class with security privileges.

  @author Jeff Schoen / Neon Ngo
*/
public class MidasThread extends Thread implements Runnable {

  /** Counter used when generating thread names for autonumbering anonymous threads. */
  private static final AtomicInteger threadCounter = new AtomicInteger();

  /** default constructor */
  public MidasThread () {}

  /** Get number of next thread
   *  @return next thread number (this will increment the existing value) for naming anonymous threads.
   *  @since NeXtMidas 3.1.1
   */
  public static int nextThreadNum () {
    // since 3.3.2: made non-synchronized by using AtomicInteger for threadCounter
    return threadCounter.incrementAndGet();
  }

  /** The Midas context to use. */
  private Midas M;

  /** The object to run in the thread. */
  private Runnable obj;

  /** Creates a new instance. <br>
      This is the same as <code>MidasThread(M, obj, null)</code>.
      @param M   The Midas context to use.
      @param obj The object to run in the thread.
  */
  public MidasThread (Midas M, Runnable obj) {
    this(M, obj, null);
  }

  /** Creates a new instance.
      @param M    The Midas context to use.
      @param obj  The object to run in the thread.
      @param name The name of the thread (helpful for debugging, use null for anonymous/generic name).
  */
  public MidasThread (Midas M, Runnable obj, String name) {
    super((name==null)? ("MidasThread-" + nextThreadNum()) : name);
    this.obj = obj;
    this.M = M;
  }

  /** Creates a new instance. <br>
      This is the same as <code>MidasThread(M, cmd, cmd.name+"-"+cmd.id)</code>.<br>
      Since NeXtMidas 2.9.3: The thread name includes the command's ID in addition to
      the command name, when cmd is not null.
      @param M   The Midas context to use.
      @param cmd The command to run in the thread.
  */
  public MidasThread (Midas M, Command cmd) {
    this(M, cmd, ((cmd==null)?null : cmd.name+(cmd.id.length()>0? "-"+cmd.id : "")) );
  }

  /** Runs the object. This extends the typical {@link Thread#run()} by
      enabling security permissions for the thread prior to starting it.
      @see Thread#run()
  */
  public void run() {
    // handle security issues
    if (M==null) {} // nothing to do here
    // now run the thread
    obj.run();
  }

}
