/* VMThread -- VM interface for Thread of executable code
   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.lang;

/**
 * VM interface for Thread of executable code. Holds VM dependent state.
 * It is deliberately package local and final and should only be accessed
 * by the Thread class.
 * <p>
 * This is the GNU Classpath reference implementation, it should be adapted
 * for a specific VM.
 * <p>
 * The following methods must be implemented:
 * <ul>
 * <li>native void start(long stacksize);
 * <li>native void interrupt();
 * <li>native boolean isInterrupted();
 * <li>native void suspend();
 * <li>native void resume();
 * <li>native void nativeSetPriority(int priority);
 * <li>native void nativeStop(Throwable t);
 * <li>native static Thread currentThread();
 * <li>static native void yield();
 * <li>static native boolean interrupted();
 * </ul>
 * All other methods may be implemented to make Thread handling more efficient
 * or to implement some optional (and sometimes deprecated) behaviour. Default
 * implementations are provided but it is highly recommended to optimize them
 * for a specific VM.
 *
 * @author Jeroen Frijters (jeroen@frijters.net)
 * @author Dalibor Topic (robilad@kaffe.org)
 */
final class VMThread
{
    /**
     * The Thread object that this VM state belongs to.
     * Used in currentThread() and start().
     * Note: when this thread dies, this reference is *not* cleared
     */
    volatile Thread thread;

    /**
     * Flag that is set when the thread runs, used by stop() to protect against
     * stop's getting lost.
     */
    private volatile boolean running;

    /**
     * VM private data.
     */
    private transient Object vmdata;

    /**
     * Private constructor, create VMThreads with the static create method.
     *
     * @param thread The Thread object that was just created.
     */
    private VMThread(Thread thread)
    {
        this.thread = thread;
    }

    /**
     * This method is the initial Java code that gets executed when a native
     * thread starts. It's job is to coordinate with the rest of the VMThread
     * logic and to start executing user code and afterwards handle clean up.
     */
    private void run()
    {
        try
        {
            try
            {
                running = true;
                synchronized(thread)
                {
                    Throwable t = thread.stillborn;
                    if(t != null)
                    {
                        thread.stillborn = null;
                        throw t;
                    }
                }
                thread.run();
            }
            catch(Throwable t)
            {
                try
                {
                  Thread.UncaughtExceptionHandler handler;
                  handler = thread.getUncaughtExceptionHandler();
                  handler.uncaughtException(thread, t);
                }
                catch(Throwable ignore)
                {
                }
            }
        }
        finally
        {
            // Setting runnable to false is partial protection against stop
            // being called while we're cleaning up. To be safe all code in
            // VMThread be unstoppable.
            running = false;
            thread.die();
            synchronized(this)
            {
                // release the threads waiting to join us
                notifyAll();
            }
        }
    }

    /**
     * Creates a native Thread. This is called from the start method of Thread.
     * The Thread is started.
     *
     * @param thread The newly created Thread object
     * @param stacksize Indicates the requested stacksize. Normally zero,
     * non-zero values indicate requested stack size in bytes but it is up
     * to the specific VM implementation to interpret them and may be ignored.
     */
    static void create(Thread thread, long stacksize)
    {
        VMThread vmThread = new VMThread(thread);
        vmThread.start(stacksize);
        thread.vmThread = vmThread;
    }

    /**
     * Gets the name of the thread. Usually this is the name field of the
     * associated Thread object, but some implementation might choose to
     * return the name of the underlying platform thread.
     */
    String getName()
    {
        return thread.name;
    }

    /**
     * Set the name of the thread. Usually this sets the name field of the
     * associated Thread object, but some implementations might choose to
     * set the name of the underlying platform thread.
     * @param name The new name
     */
    void setName(String name)
    {
        thread.name = name;
    }

    /**
     * Set the thread priority field in the associated Thread object and
     * calls the native method to set the priority of the underlying
     * platform thread.
     * @param priority The new priority
     */
    void setPriority(int priority)
    {
        thread.priority = priority;
        nativeSetPriority(priority);
    }

    /**
     * Returns the priority. Usually this is the priority field from the
     * associated Thread object, but some implementation might choose to
     * return the priority of the underlying platform thread.
     * @return this Thread's priority
     */
    int getPriority()
    {
        return thread.priority;
    }

    /**
     * Returns true if the thread is a daemon thread. Usually this is the
     * daemon field from the associated Thread object, but some
     * implementation might choose to return the daemon state of the underlying
     * platform thread.
     * @return whether this is a daemon Thread or not
     */
    boolean isDaemon()
    {
        return thread.daemon;
    }

    /**
     * Returns the number of stack frames in this Thread.
     * Will only be called when when a previous call to suspend() returned true.
     *
     * @deprecated unsafe operation
     */
    native int countStackFrames();

    /**
     * Wait the specified amount of time for the Thread in question to die.
     *
     * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
     * not offer that fine a grain of timing resolution. Besides, there is
     * no guarantee that this thread can start up immediately when time expires,
     * because some other thread may be active.  So don't expect real-time
     * performance.
     *
     * @param ms the number of milliseconds to wait, or 0 for forever
     * @param ns the number of extra nanoseconds to sleep (0-999999)
     * @throws InterruptedException if the Thread is interrupted; it's
     *         <i>interrupted status</i> will be cleared
     */
    synchronized void join(long ms, int ns) throws InterruptedException
    {
        // Round up
        ms += (ns != 0) ? 1 : 0;

        // Compute end time, but don't overflow
        long now = System.currentTimeMillis();
        long end = now + ms;
        if (end < now)
            end = Long.MAX_VALUE;

        // A VM is allowed to return from wait() without notify() having been
        // called, so we loop to handle possible spurious wakeups.
        while(thread.vmThread != null)
        {
            // We use the VMThread object to wait on, because this is a private
            // object, so client code cannot call notify on us.
            wait(ms);
            if(ms != 0)
            {
                now = System.currentTimeMillis();
                ms = end - now;
                if(ms <= 0)
                {
                    break;
                }
            }
        }
    }

    /**
     * Cause this Thread to stop abnormally and throw the specified exception.
     * If you stop a Thread that has not yet started, the stop is ignored
     * (contrary to what the JDK documentation says).
     * <b>WARNING</b>This bypasses Java security, and can throw a checked
     * exception which the call stack is unprepared to handle. Do not abuse
     * this power.
     *
     * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
     * leave data in bad states.
     *
     * <p><b>NOTE</b> stop() should take care not to stop a thread if it is
     * executing code in this class.
     *
     * @param t the Throwable to throw when the Thread dies
     * @deprecated unsafe operation, try not to use
     */
    void stop(Throwable t)
    {
        // Note: we assume that we own the lock on thread
        // (i.e. that Thread.stop() is synchronized)
        if(running)
            nativeStop(t);
        else
            thread.stillborn = t;
    }

    /**
     * Create a native thread on the underlying platform and start it executing
     * on the run method of this object.
     * @param stacksize the requested size of the native thread stack
     */
    native void start(long stacksize);

    /**
     * Interrupt this thread.
     */
    native void interrupt();

    /**
     * Determine whether this Thread has been interrupted, but leave
     * the <i>interrupted status</i> alone in the process.
     *
     * @return whether the Thread has been interrupted
     */
    native boolean isInterrupted();

    /**
     * Suspend this Thread.  It will not come back, ever, unless it is resumed.
     */
    native void suspend();

    /**
     * Resume this Thread.  If the thread is not suspended, this method does
     * nothing.
     */
    native void resume();

    /**
     * Set the priority of the underlying platform thread.
     *
     * @param priority the new priority
     */
    native void nativeSetPriority(int priority);

    /**
     * Asynchronously throw the specified throwable in this Thread.
     *
     * @param t the exception to throw
     */
    native void nativeStop(Throwable t);

    /**
     * Return the Thread object associated with the currently executing
     * thread.
     *
     * @return the currently executing Thread
     */
    static native Thread currentThread();

    /**
     * Yield to another thread. The Thread will not lose any locks it holds
     * during this time. There are no guarantees which thread will be
     * next to run, and it could even be this one, but most VMs will choose
     * the highest priority thread that has been waiting longest.
     */
    static native void yield();

    /**
     * Suspend the current Thread's execution for the specified amount of
     * time. The Thread will not lose any locks it has during this time. There
     * are no guarantees which thread will be next to run, but most VMs will
     * choose the highest priority thread that has been waiting longest.
     *
     * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
     * not offer that fine a grain of timing resolution. Besides, there is
     * no guarantee that this thread can start up immediately when time expires,
     * because some other thread may be active.  So don't expect real-time
     * performance.
     *
     * @param ms the number of milliseconds to sleep.
     * @param ns the number of extra nanoseconds to sleep (0-999999)
     * @throws InterruptedException if the Thread is (or was) interrupted;
     *         it's <i>interrupted status</i> will be cleared
     */
    static void sleep(long ms, int ns) throws InterruptedException
    {
      // Note: JDK treats a zero length sleep is like Thread.yield(),
      // without checking the interrupted status of the thread.
      // It's unclear if this is a bug in the implementation or the spec.
      // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203
      if (ms == 0 && ns == 0)
        {
          if (Thread.interrupted())
            throw new InterruptedException();
          return;
        }

      // Compute end time, but don't overflow
      long now = System.currentTimeMillis();
      long end = now + ms;
      if (end < now)
          end = Long.MAX_VALUE;

      // A VM is allowed to return from wait() without notify() having been
      // called, so we loop to handle possible spurious wakeups.
      VMThread vt = Thread.currentThread().vmThread;
      synchronized (vt)
        {
          while (true)
            {
              vt.wait(ms, ns);
              now = System.currentTimeMillis();
              if (now >= end)
                break;
              ms = end - now;
              ns = 0;
            }
        }
    }

    /**
     * Determine whether the current Thread has been interrupted, and clear
     * the <i>interrupted status</i> in the process.
     *
     * @return whether the current Thread has been interrupted
     */
    static native boolean interrupted();

    /**
     * Checks whether the current thread holds the monitor on a given object.
     * This allows you to do <code>assert Thread.holdsLock(obj)</code>.
     *
     * @param obj the object to check
     * @return true if the current thread is currently synchronized on obj
     * @throws NullPointerException if obj is null
     */
    static boolean holdsLock(Object obj)
    {
      /* Use obj.notify to check if the current thread holds
       * the monitor of the object.
       * If it doesn't, notify will throw an exception.
       */
      try
        {
          obj.notify();
          // okay, current thread holds lock
          return true;
        }
      catch (IllegalMonitorStateException e)
        {
          // it doesn't hold the lock
          return false;
        }
    }

  /**
   * Returns the current state of the thread.
   * The value must be one of "BLOCKED", "NEW",
   * "RUNNABLE", "TERMINATED", "TIMED_WAITING" or
   * "WAITING".
   *
   * @return a string corresponding to one of the
   *         thread enumeration states specified above.
   */
  native String getState();

}
