/*
 *  ZThreads, a platform-independant, multithreading and 
 *  synchroniation library
 *
 *  Copyright (C) 2001, 2002 Eric Crahen, See LGPL.TXT for details
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 *  SUNY @ Buffalo, hereby disclaims all copyright interest in the
 *  ZThreads library written by Eric Crahen
 */

#include "POSIX_ThreadImpl.h"
#include "POSIX_ThreadManager.h"
#include "ValueHolder.h"

#include <assert.h>

#include <errno.h>
#include <unistd.h>

#include <time.h>
#include <sys/time.h>
#include <signal.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#if defined(HAVE_SCHED_YIELD)
#include <sched.h>
#endif
#endif

using namespace ZThread;

FastThreadLocal<ThreadImpl*> ThreadImpl::_threadMap;

/**
 * Initialize a new ThreadImpl object.
 */
ThreadImpl::ThreadImpl() 
  throw(Synchronization_Exception) : _joiner(0), _tid(0), _count(0) {

  ZTDEBUG("Thread created.\n");

}

/**
 * Destroy the ThreadImpl 
 */
ThreadImpl::~ThreadImpl() 
  throw() {

  // Make sure the threads state has IDLE, KILLED, JOINED or a REFERENCE bits
  int state = _monitor->state() & (State::KILLED|State::JOINED|State::REFERENCE|State::IDLE);
  if(!state) {

    ZTDEBUG("You are destroying an executing thread! 0x%08X\n", _monitor->state());
    assert(0);
    
  }

  assert(_count == 0);
  ZTDEBUG("Thread destroyed.\n");

}


/**
 * Increment the reference count on this object. It will take one more 
 * release() for this object to be destroyed.
 */
void ThreadImpl::acquire() {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally.
  Guard<MONITOR> g(_monitor);
  _count++;

}

/**
 * Decrement the reference count on this object, it will cause this object
 * to destroy itself once the count has reaches zero.
 */
bool ThreadImpl::release() {

  bool result;

  {

    // Acquire the Monitor with a Guard. This will automatically
    // unlock when an exception is thrown or when the method returns
    // normally.
    Guard<MONITOR> g(_monitor);
    result = (--_count == 0);
    
  }

  if(result) // No members are every touch again after this is invoked
    delete this;

  return result;

}


/**
 * Transition the thread to the KILLED state. The thread will be interrupt()ed
 * once after the state change, using the sticky-ness of the monitor to make 
 * sure the thread does not block on its Monitor. 
 *
 * If the thread is not interrupted, then wherever there is a lack of atomicity
 * there is a chance a thread could be killed and then go to sleep, waiting for
 * a signal that may never come.
 *
 * Reference threads are not under the control of ZThreads and cannot be
 * joined.
 *
 * @exception Unexpected_Exception thrown if this thread is already KILLED 
 * @exception InvalidOp_Exception thrown if the thread being joined is invalid 
 * (e.g. KILLED, JOINED, etc)
 */
void ThreadImpl::kill() 
  throw(Synchronization_Exception) {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally.
  Guard<MONITOR> g(_monitor);

  // Make sure a thread is not trying to kill itself.
  if(pthread_equal(pthread_self(), _tid))
    throw InvalidOp_Exception("Cannot commit suicide.");
  
  // Throw if the thread has already been KILLED
  if(_monitor->check(State::KILLED))
    throw Unexpected_Exception("Can not kill a killed thread.");

  // If this is not a REFERENCE thread, attempt to transition to the 
  // KILLED state.
  if(_monitor->check(State::REFERENCE) || !_monitor->transition(State::KILLED))
    throw InvalidOp_Exception("Can not kill this thread.");

  // Interrupt any wait that could be blocking the thread represented
  // by this object.
  if(_monitor.hasWaiter())
    _monitor.notify();

  // Let the ThreadManager clean up after this thread since it can not
  // be joined.
  ThreadManager::instance()->detachThread(this);
  _count++;

}


/**
 * Join the thread, blocking the caller until it is interrupted or until
 * the thread represented by this object exits.
 *
 * Reference threads are not under the control of ZThreads and cannot be
 * joined.
 *
 * @exception Deadlock_Exception thrown if thread attempts to join itself.
 * @exception InvalidOp_Exception thrown if the thread being joined is invalid 
 * (e.g. KILLED, JOINED, etc)
 * @exception Interrupted_Exception thrown if the joining thread is INTERRUPTED.
 * @exception Unexpected_Exception thrown if the joining thread is KILLED.
 */
bool ThreadImpl::join(unsigned long timeout) 
  throw(Synchronization_Exception) {

  bool wasInterrupted = false;
  bool wasJoining = false;
  bool wasKilled = false;
  bool wasOnTime = true;

  {

    // Acquire the Monitor with a Guard. This will automatically
    // unlock when an exception is thrown or when the method returns
    // normally.
    Guard<MONITOR> g(_monitor);
    
    // Make sure a thread is not trying to kill itself.
    if(pthread_equal(pthread_self(), _tid))
      throw Deadlock_Exception("Cannot join self.");
       
    // Cannot join DAEMON, IDLE, REFERENCE, JOINED or KILLED threads 
    if(_monitor->check(State::DAEMON|State::IDLE|State::REFERENCE|State::JOINED|State::KILLED)) 
      throw InvalidOp_Exception("Can not join this thread.");

    // If this thread is already being join()ed, throw an exception
    if(!_joiner) {

      _joiner = current();
      
      // Should enhance to check entire chain of joining
      if(_joiner->_joiner == this) {
        _joiner = 0;
        throw Deadlock_Exception("Cyclic join\n");
      }
      
    }

    else throw InvalidOp_Exception("Thread already being joined.");

    // Set a flag if the thread represented by this object has already exited.
    wasJoining = _monitor->check(State::JOINING);
    
    // If there is no need to wait to enter the JOINING state, because we are
    // already there, attempt to transition to the JOINED state.
    if(wasJoining) {

      // Throw if the transition cannot be made
      if(!_monitor->transition(State::JOINED)) 
        throw Synchronization_Exception("Error joining thread.");

    }

  }

  // If the thread is not yet in the JOINING state then an interruptable wait
  // is performed. If the thread is in the JOINING state then this wait is 
  // simply avoided.

  if(!wasJoining) {

    // The _joiner will be notify()ed when the thread represented by this
    // object exits. Even though there is no atomicity here, the sticky-ness 
    // of the Monitor for the waiting thread should avoid a lost signal.
    
    _joiner->_monitor.acquire();

    if(wasOnTime = _joiner->_monitor.wait(timeout)) {
    
      // Joiner has been awakened. Check if its state was INTERRUPTED or KILLED
      wasKilled = _joiner->_monitor->check(State::KILLED);
      wasInterrupted = _joiner->_monitor->check(State::INTERRUPTED);
      if(wasInterrupted)
        _joiner->_monitor->clear(State::INTERRUPTED);
      

    }

    _joiner->_monitor.release();


    // The wait succeeded or the thread was interrupted, in either case, 
    // update the _joiner for this thread in either case. No other thread
    // can start to join here as long as the _joiner value is non-null.
    {
      
      // Acquire the Monitor with a Guard. This will automatically
      // unlock when an exception is thrown or when the method returns
      // normally.
      Guard<MONITOR> g(_monitor);
      
      // Remove the joiner
      _joiner = 0;
      
      // Attempt to transition to the JOINED state.
      if(wasOnTime && !wasInterrupted && !_monitor->transition(State::JOINED)) 
        throw Synchronization_Exception("Error joining thread.");
       
    }
  
  }

  // Check the state and throw an exception if needed.
  if(wasKilled)
    throw Unexpected_Exception();

  if(wasInterrupted)
    throw Interrupted_Exception();

  if(wasOnTime) {

    // Finally, allow the joiner to actually join the thread. This should not 
    // block very long because thread is already done at this point.
    ZTCHECK(pthread_join(_tid, NULL));

  }

  return wasOnTime;

}

/**
 * Dispatch a the native thread to run the task. 
 *
 * @param task Runnable* to the task object to execture
 */
void ThreadImpl::run(Runnable *task) 
  throw(Synchronization_Exception) {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally.
  Guard<MONITOR> g(_monitor);

  // Check the state, a Thread must still be IDLE in order to
  // be eligable to run a task.
  if(!_monitor->check(State::IDLE))
    throw InvalidOp_Exception("Thread is not idle.");

  // Create a new the thread
  ThreadImpl* parent = current(); 
  Params params(parent, this, task);

  // Acquire the parent monitor in order to safely wait for the child
  parent->_monitor.acquire();

  if(pthread_create(&_tid, 0, _dispatch, &params) != 0)
    throw Synchronization_Exception("Could not create posix thread.");
  
  // Wait for the new thread to start executing, ignore signals from
  // interruption, etc until the child starts.
  int first, last;

  do {

    first = parent->_monitor->state();
    parent->_monitor.wait();
    last = parent->_monitor->state();
    
    
  } while(first != last);

  parent->_monitor.release();


}



/** 
 * Interrupt this thread. The caller *must* hold the monitor lock.
 *
 * To write some piece of code that can be notified of a Thread::interrupt()
 * use a block of code similar to this
 *
 * // Implement a timeout for accept
 *  sigjmp_buf timeout_jmp;
 *  if(sigsetjmp(timeout_jmp, 1) != 0)
 *    throw IOInterrupted_Exception();
 *
 *  // Enable the timeout
 *  ZThread::Thread::interruptKey().set(&timeout_jmp);
 *
 *  // Do some lengthy operation.
 *
 *  // Disable the timeout
 *  ZThread::Thread::interruptKey().set(NULL);
 *
 */
void ThreadImpl::interrupt() 
  throw(Synchronization_Exception) {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor);

  // If the thread is KILLED throw and interrupted exception
  if(_monitor->check(State::KILLED))
    throw Unexpected_Exception();

  // Set the INTERRUPTED flag if it has not been set, if the thread
  // is RUNNING or IDLE.
  if(!_monitor->check(State::IDLE|State::RUNNING)) 
    throw InvalidOp_Exception();

  else if(!_monitor->check(State::INTERRUPTED)) {

    _monitor->set(State::INTERRUPTED);

    // If the calling thread is represented by this thread object, its
    // obvisouly not blocked, so don't attempt to signal. 
    // Otherwise, distribute signals & notification.
    if(pthread_equal(pthread_self(), _tid) == 0) {

#if !defined(DISABLE_IO_INTERRUPT)

      // Raise a signal to interrupt any system level I/O that
      // could be in progress if the thread is not blocked.
      if(!_monitor.hasWaiter()) 
        pthread_kill(_tid, SIGALRM);
    
#endif

    }

    // Set the monitor to make sure the thread won't wait() only when running
    // so that IDLE threads starting up are not interfered with.
    if(_monitor->check(State::RUNNING))
      _monitor.notify();    

    ZTDEBUG("Thread interrupted.\n");

  }  

}

/**
 * Translate the priority into a pthread value, and update the thread priority.
 *
 * This is not available on all platforms, and probably works differently 
 * the platforms that do support it. Pthreads does not have very portable 
 * priority support as far I am aware.
 *
 * If SCHED_OTHER is not supported priority values are still set but  
 * dont not actually in affect anything.
 *
 * @param prio Thread::PRIORITY value
 *
 * @exception Unexpected_Exception thrown by KILLED threads.
 * @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads.
 */
void ThreadImpl::setPriority(Thread::PRIORITY prio)
  throw(Synchronization_Exception) {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 

  // Check for a KILLED thread.
  if(_monitor->check(State::KILLED))
    throw Unexpected_Exception();

  // Update RUNNING threads.
  if(_monitor->check(State::RUNNING)) {

#if !defined(DISABLE_THREAD_PRIO)

    struct sched_param param;
    
    // Convert
    switch(prio) {
      case Thread::PRI_LOW:
        param.sched_priority = 0;
        break;
      case Thread::PRI_HIGH:
        param.sched_priority = 10;
        break;
      case Thread::PRI_NORMAL:
      default:
        param.sched_priority = 5;
    }

    param.sched_priority = 0;
  
    if(pthread_setschedparam(_tid, SCHED_OTHER, &param) != 0)
      throw Synchronization_Exception("Error setting priority");   
    
#endif

  } else
    throw InvalidOp_Exception();

}


/**
 * Translate the pthread value into a priority, using SCHED_OTHER.
 *
 * This is not available on all platforms, and probably works differently 
 * the platforms that do support it. Pthreads does not have very portable 
 * priority support as far I am aware.
 *
 * If SCHED_OTHER is not supported priority values are still reported but  
 * are not actually in effect.
 *
 * @return Thread::PRIORITY
 *
 * @exception Unexpected_Exception thrown by KILLED threads.
 * @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads.
 */
Thread::PRIORITY ThreadImpl::getPriority()
  throw(Synchronization_Exception) {

  Thread::PRIORITY prio = Thread::PRI_NORMAL;

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 

  // Check for a KILLED thread.
  if(_monitor->check(State::KILLED))
    throw Unexpected_Exception();

  // Check RUNNING threads.
  if(_monitor->check(State::RUNNING)) {
    
#if !defined(DISABLE_THREAD_PRIO)

    struct sched_param param;
    int policy = SCHED_OTHER;
    
    if(pthread_getschedparam(_tid, &policy, &param) != 0)
      throw Synchronization_Exception("Error getting priority");
    
    // Convert to one of the Thread::PRIORITY values
    if(param.sched_priority < 10)
      prio = Thread::PRI_LOW;
    else if(param.sched_priority == 10)
      prio = Thread::PRI_NORMAL;
    else
      prio = Thread::PRI_HIGH;

#endif
  
    
  } else
    throw InvalidOp_Exception();

  return prio;
  
}

/**
 * Test the state Monitor of this thread to determine if the thread is IDLE or RUNNING
 * bits are set.
 *
 * @return bool indicating the status of the thread when this method is called
 */
bool ThreadImpl::isActive() throw() {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 
  return (_monitor->check(State::IDLE|State::RUNNING));

}

/**
 * Test the state Monitor of this thread to determine if the DAEMON
 * bit is set.
 *
 * @return bool indicating the status of the DAEMON bit when the method 
 * is called.
 */
bool ThreadImpl::isDaemon() throw() {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 
  return (_monitor->check(State::DAEMON));

}


/**
 * Test the state Monitor of this thread to determine if the INTERRUPTED
 * bit is set. If it is set, and the currently executing thread is mapped
 * onto this Thread object that bit will be cleared. 
 *
 * @return bool indicating the status of the INTERRUPTED bit when the method 
 * is called.
 */
bool ThreadImpl::isInterrupted() throw() {
  
  bool result = false;

  // Lock the Monitor so the state can be examined
  Guard<MONITOR> g(_monitor);
  
  // Check the thread state is INTERRUPTED and is RUNNING or IDLE
  if(_monitor->check(State::IDLE|State::RUNNING) && _monitor->check(State::INTERRUPTED)) {

    // If the current thread is represented by this object, clear the bit
    if(pthread_equal(pthread_self(), _tid)) 
      _monitor->clear(State::INTERRUPTED);

    result = true;

  }

  return result;
  
}


/**
 * Test the state Monitor of this thread to determine if the KILLED
 * bit is set.
 *
 * @return bool indicating the status of the KILLED bit when the method 
 * is called.
 */
bool ThreadImpl::isKilled() throw() {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 
  return (_monitor->check(State::KILLED));

}

/**
 * Test the state Monitor of this thread to determine if the NOTIFY
 * bit is set.
 *
 * @return bool indicating the status of the NOTIFY bit when the method 
 * is called.
 */
bool ThreadImpl::wantNotify() throw() {

  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 
  return (_monitor->check(State::NOTIFY));

}


/**
 * Set the DAEMON status bit on the state Monitor for this Thread. A 
 * Thread must be in the RUNNING or IDLE state for this to be successful.
 *
 *
 * @param flag if true set the DAEMON bit, otherwise clear it.
 *
 * @exception Unexpected_Exception thrown by KILLED threads.
 * @exception InvalidOp_Exception thrown by REFERENCE, JOINING or JOINED threads.
 */
void ThreadImpl::setDaemon(bool flag)
  throw(Synchronization_Exception) {
  
  // Acquire the Monitor with a Guard. This will automatically
  // unlock when an exception is thrown or when the method returns
  // normally. 
  Guard<MONITOR> g(_monitor); 

  // Check for a KILLED thread.
  if(_monitor->check(State::KILLED))
    throw Unexpected_Exception();

  // Update Non-REFERENCE RUNNING or IDLE threads.
  if(!_monitor->check(State::REFERENCE) && _monitor->check(State::RUNNING|State::IDLE)) {

    bool isSet = _monitor->check(State::DAEMON);

    // Toggle the DAEMON status on or off
    if(flag && !isSet) {

      ZTDEBUG("Toggled DAEMON bit ON.\n");

      _monitor->set(State::DAEMON);

      // Detach the thread if it is RUNNING, an IDLE thread
      // will be detach when it is started and has a valid id
      if(_monitor->check(State::RUNNING)) {
         ThreadManager::instance()->detachThread(this);
         _count++;
      }

    } else if(isSet) { 

      ZTDEBUG("Toggled DAEMON bit OFF.\n");

      _monitor->clear(State::DAEMON);

      // Attach the thread if it is RUNNING, an IDLE thread
      // will be detach when it is started and has a valid id
      if(_monitor->check(State::RUNNING)) {
         ThreadManager::instance()->attachThread(this);
         _count--;
      }

    }

  } else 
    throw InvalidOp_Exception();

}


/**
 * Set the NOTIFY status bit on the state Monitor for this Thread. A 
 * Thread must be in the RUNNING or IDLE state for this to be successful.
 *
 * @param flag if true set the NOTFIY bit, otherwise clear it.
 *
 * @exception Unexpected_Exception thrown by KILLED threads.
 * @exception InvalidOp_Exception thrown by REFERENCE, JOINING or JOINED threads.
 */
void ThreadImpl::setNotify(bool flag) 
  throw(Synchronization_Exception) {
  
  // Check for a KILLED thread.
  if(_monitor->check(State::KILLED))
    throw Unexpected_Exception();

  // Update Non-REFERENCE RUNNING or IDLE threads.
  if(!_monitor->check(State::REFERENCE) && _monitor->check(State::RUNNING|State::IDLE)) {

    if(flag) {

      ZTDEBUG("Toggled NOTIFY bit ON.\n");
      _monitor->set(State::NOTIFY);    

    } else {

      ZTDEBUG("Toggled NOTIFY bit OFF.\n");
      _monitor->clear(State::NOTIFY);    

    }

  } else 
    throw InvalidOp_Exception();

}


/**
 * Get a reference to an implmenetation that maps to the current thread.
 * Accomplished by checking the TLS map. This will always return a valid
 * ThreadImpl instance.
 *
 * @return ThreadImpl* current implementation that maps to the
 * executing thread.
 */ 
ThreadImpl* ThreadImpl::current()
  throw(Synchronization_Exception) {

  // Get the ThreadImpl previously mapped onto the executing thread.
  ThreadImpl* impl = _threadMap.get();

  // Create a reference thread for any threads that have been 'discovered'
  // because they are not created by ZThreads.
  if(impl == 0) { 
   
    // Create a ThreadImpl to represent this thread. 
    impl = new ThreadImpl();
    impl->_tid = pthread_self();

    // Set its state to RUNNING and mark it as a REFERENCE thread.
    impl->_monitor->set(State::REFERENCE|State::RUNNING);
    impl->_count++;

    // Map a reference thread 
    _threadMap.set(impl);
    ThreadManager::instance()->referenceThread(impl);

  }
  
  assert(impl != 0);
  return impl;

}

/**
 * Make current thread sleep for the given number of milliseconds.
 * This sleep can be interrupt()ed.
 * 
 * @param ms timeout for the sleep.
 *
 * @post the calling thread is blocked by waiting on the internal condition
 * variable. This can be signaled in the monitor of an interrupt
 */
void ThreadImpl::sleep(unsigned long ms) 
  throw(Synchronization_Exception) {
  
  // Get the ThreadImpl mapped to the excuting thread
  ThreadImpl* impl = current();
  
  // Acquire that threads Monitor with a Guard
  Guard<MONITOR> g(impl->_monitor);

  bool hasWaited = false;

  for(;;) {

    // KILLED threads should throw an unexpected exception
    if(impl->_monitor->check(State::KILLED))
      throw Unexpected_Exception("Thread has been killed.");
    
    // JOINED threads are also not eligable to sleep.
    if(impl->_monitor->check(State::JOINED))
      throw InvalidOp_Exception("Thread has been joined.");
    
    // Check the INTERRUPTED flag, clear and throw if set
    if(impl->_monitor->check(State::INTERRUPTED)) {
      
      impl->_monitor->clear(State::INTERRUPTED);
      throw Interrupted_Exception();
      
    }
    
    // Wait for the timeout or a signal only if the thread has not 
    // yet waited. If the wait timedout then just return.
    if(ms == 0 || hasWaited || !impl->_monitor.wait(ms))
      return;
    
    // Run through the checks once more if the wait recieved a signal.
    hasWaited = true;

  }

}


/**
 * Yield the current timeslice to another thread. 
 * If sched_yield() is available it is used. 
 * Otherwise, the state Monitor for this thread is used to simiulate a
 * yield by blocking for 1  millisecond, which should give the 
 * scheduler a chance to schedule another thread.
 */
void ThreadImpl::yield() throw() {

#if defined(HAVE_SCHED_YIELD)

  sched_yield();

#else

  // Get the ThreadImpl mapped to the excuting thread
  ThreadImpl* impl = current();

  // Acquire that threads Monitor with a Guard
  Guard<MONITOR> g(impl->_monitor);

  // Simulate a yield by waiting for 1 millisecond
  impl->_monitor.wait(1);

#endif

}


/**
 * Create a new ValueHoler that is associated with this ThreadImpl.
 * These objects will be destroyed just before the thread exits.
 *
 * @param tls the ThreadLocal associated with the ValueHolder, this is 
 * used to propogate values to the children threads
 * @param value initial value to give the holder.
 * @param inheritable ValueHolders marked as inheritable are stored
 * in a separate list so that thier values can be copies when new
 * children are spawned.
 */
ValueHolder* ThreadImpl::createValueHolder(const AbstractThreadLocal* tls, 
                                           void* value, bool inheritable) {

  ValueHolder* holder = new ValueHolder(tls, value);

  if(inheritable)
    _inheritableKeys.push_back(holder);
  else
    _keys.push_back(holder);
    
  return holder;

}

/**
 * Static native dispatch method. This is called as each thread is dispatched
 * for the first time. It performs the following steps.
 *
 * Initialization:
 *
 * 1. Map this Thread object onto the running thread.
 * 2. Detach the thread if it is a DAEMON thread.
 * 3. Transition to the RUNNING state.
 *
 * Running:
 *
 * 4. Release the parent, who is waiting for this thread to start.
 * 5. Run the task this thread was given.
 *
 * Exiting:
 *
 * 6. Transition to the JOINING state.
 * 7. Notify a thread waiting to join this thread that it is about to exit.
 * 8. Exit.
 */
void *ThreadImpl::_dispatch(void *arg) {

  Params *params = (Params*)arg;

  ThreadImpl* parent = params->parent;
  ThreadImpl* impl = params->child;
  Runnable *task = params->task;

  // Map the implementation object onto this thread.
  _threadMap.set(impl);

  {
    // Acquire the Monitor with a Guard. This will automatically
    // unlock when an exception is thrown or when the method returns
    // normally.
    Guard<MONITOR> g(parent->_monitor);

    // The child is implicitly guared by the parent since it will not unlock
    // until it is signled at the end of the block.

    // Propogate ThreadLocal values to child
    KeyList::iterator i = parent->_inheritableKeys.begin();
    for(;i != parent->_inheritableKeys.end(); ++i) {
      
      // Get the value holder for the parent
      ValueHolder* holder = *i;
      const AbstractThreadLocal* tls = holder->getThreadLocal();
      
      // Invoke the childValue() for each value
      void* value = tls->childValue(holder->getValue());
      holder->getThreadLocal()->set(value);
    
    }

    // Move to the RUNNING state once the thread is properly initialized
    impl->_monitor->transition(State::RUNNING);

    // Detach this thread if it was a daemon thread
    if(impl->_monitor->check(State::DAEMON)) {
 
      ThreadManager::instance()->detachThread(impl); 
      impl->_count++; 

    }

    // Notify() the monitor for this thread once execution has started, unblocking
    // the thread which spawned this one.
    parent->_monitor.notify();

  }


  // Give the scheduler a chance resume another thread before the task is executed.
  yield();

  ZTDEBUG("Thread starting...\n");

  try {
    
    if(task != (Runnable*)0)
      task->run();
    
  } catch(InvalidTask_Exception& e) {

    // Result of running non-extended thread   
    ZTDEBUG("An invalid task was run!\n");
    
  } catch(...) {

    // Result of running a task that threw an exception.
    ZTDEBUG("The task has thrown an unhandled exception\n");
    
  }

  ZTDEBUG("Thread joining...\n"); 

  {
    // Re-acquire the monitor for this thread
    Guard<MONITOR> g(impl->_monitor);

    // While the lock is held transition to the JOINING state.
    impl->_monitor->transition(State::JOINING);

    // If there is a thread blocked on join() awaken it.
    ThreadImpl* joiner = impl->_joiner;
    if(joiner) {

      joiner->_monitor.acquire();
      joiner->_monitor.notify();
      joiner->_monitor.release();

    }

  }

  ZTDEBUG("Thread exiting...\n"); 

  // Cleanup thread keys
  for(KeyList::iterator i = impl->_keys.begin(); i != impl->_keys.end(); ++i)
    delete *i;

  for(KeyList::iterator i = impl->_inheritableKeys.begin(); i != impl->_inheritableKeys.end(); ++i)
    delete *i;

  // Exit the thread
  pthread_exit( (void**)0 );
  return (void*)0;
  
}





