#if !defined(__THREADCONTEXT_HPP)
#define __THREADCONTEXT_HPP

/*
  CoreLinux++ 
  Copyright (C) 1999,2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/

#if   !defined(__COMMON_HPP)
#include <Common.hpp>
#endif

#if   !defined(__THREADEXCEPTION_HPP)
#include <ThreadException.hpp>
#endif

namespace corelinux
{

   /// Thread state enumeration 

   enum  ThreadState
   {
      /// The thread is waiting to be started

      THREAD_WAITING_TO_START = 0,

      /// The thread is in the process of starting

      THREAD_STARTING,

      /// The thread is running

      THREAD_RUNNING,

      /// Thread completed without exception

      THREAD_NORMAL_EXIT,

      /// Thread never started with exception

      THREAD_START_EXCEPTION,

      /// Thread has died with exception

      THREAD_EXCEPTION,

      /// Thread never started

      THREAD_START_FAILED

   };


   DECLARE_CLASS( ThreadContext );

   /**
   Callers function entry point
   @param ThreadContext object instance pointer
   @return int return code
   */

   typedef  int (*CallerFunctionPtr)(ThreadContextPtr);  

   /**
   Thread frame entry point function handler
   @param ThreadContext pointer to managed ThreadContext
   @return Int return code from caller thread
   */

   typedef  Int (*ThreadFrameFunctionPtr)( ThreadContextPtr );

   /**
   Managed ThreadContext creation function. This is declared so that callers 
   may change the allocation routine (to map somewhere or instantiate a 
   derived ThreadContext for example ). The default handler uses the global 
   new operator.
   @param ThreadContext reference to the callers inital ThreadContext
   @return ThreadContext pointer to managed ThreadContext
   */

   typedef  ThreadContextPtr (*ThreadContextCreatePtr)( ThreadContextRef );

   /**
   Managed ThreadContext deallocate function. This is declared so that 
   callers may change the deallocation of the managed ThreadContext. 
   You would normally do this if you have substituted the 
   ThreadContextCreatePtr as well.
   @param ThreadContext pointer to managed ThreadContext.
   @return nothing
   */

   typedef  void  (*ThreadContextDestroyPtr)( ThreadContextPtr );

   /**
   Managed ThreadContext stack creation function. This is declared so that
   callers may change the allocation for the threads stack.
   The default handler uses the global new operator.
   @param ThreadContext pointer to managed ThreadContext
   @return Byte pointer to bottom of stack.
   */

   typedef  BytePtr (*ThreadStackCreatePtr)( ThreadContextPtr );

   /**
   Managed ThreadContext stack deallocate function. This is declared so 
   that callers may change the deallocation of the threads stack. You would 
   normally do this if you have substituted the ThreadStackCreatePtr 
   as well.
   @param Byte pointer as contained by ThreadContext.
   @return nothing
   */

   typedef  void  (*ThreadStackDestroyPtr)( BytePtr );

   /**
   ThreadContext describes the context in which the thread
   operates. Included are stack resource, shared address space
   flags, factory methods, and state indicators.
   */

   class ThreadContext : public Synchronized
   {

   public:

      //
      // Constructors and destructor
      //

                        /**
                        Default constructor only requires a caller entry
                        point function. Defaults in effect are 8k stack
                        which is allocated by the system, and all resources
                        of the caller are shared by the new thread.
                        @param CallerFunction pointer to the callers thread
                        routine.
                        @exception Assertion if pointer is null
                        */

                        ThreadContext( CallerFunctionPtr )
                           throw ( Assertion );

                        /**
                        Constructor which allows the caller to define the
                        stack. All resources of the caller are shared by
                        the new thread.
                        @param CallerFunction pointer to the callers thread
                        routine.
                        @param Size Request size for stack in number of 
                        bytes.
                        @exception Assertion if routine pointer is null or
                        callers stack size is negative.
                        */
                        
                        ThreadContext( CallerFunctionPtr, Size )
                           throw ( Assertion );

                        /**
                        Copy constructor takes information from the 
                        context argument.
                        @param ThreadContext reference to existing context
                        @exception ThreadNotWaitingException if the
                        argument context is not in a THREAD_WAITING_TO_START
                        state.
                        */

                        ThreadContext( ThreadContextCref )
  //                         throw ( ThreadNotWaitingException, Assertion );
                           throw ( Assertion );

                        /// Virtual destructor

      virtual           ~ThreadContext( void );

      //
      // Operator overloads
      //

               /**
               Assignment operator changes the context
               @param ThreadContext reference to existing context
               @return ThreadContext reference
               @exception ThreadNotWaitingException if the
               argument context is not in a THREAD_WAITING_TO_START
               state.
               */

               ThreadContextRef  operator=( ThreadContextCref )
                  throw( Assertion );

               /**
               Equality operator compares contexts
               @param ThreadContext reference to existing context
               @return bool true if same
               */
               
               bool  operator==( ThreadContextCref ) const;

               /**
               Equality matches the thread identifiers
               @param ThreadIdentifier reference to identifier
               @return bool true if same
               */

               bool  operator==( ThreadIdentifierCref ) const;

               /**
               Equality operator matches the callers function
               @param CallerFunctionPtr a function reference
               @return bool true if same.
               */

               bool  operator==( CallerFunctionPtr ) const;

               /**
               Coerces ThreadContext to ThreadIdentifier
               @return ThreadIdentifier reference
               */
                     operator ThreadIdentifierCref( void ) const;
      //
      // Accessors
      //

               /**
               Get the state of the thread as reflected in
               its context
               @return ThreadState
               */

               const ThreadState &  getState( void ) const;

               /**
               Get the size of the stack as defined by
               the context constructor
               @return Size in bytes
               */

               Size     getStackSize( void ) const;

               /**
               Get the share mask for the thread which
               determines VM, FILES, FILESYSTEM, SIGNAL
               shares.
               @return Int 
               */

               Int      getShareMask( void ) const;

               /**
               Return the code returned by the callers
               function. This is only valid if the
               thread ended normally
               @return Int return code
               @see ThreadState
               */

               Int      getReturnCode( void ) const;

               /**
               Get the identifier for the thread. This
               is only valid once a thread is started
               @return ThreadIdentifier the id
               */

               ThreadIdentifierCref getIdentifier( void ) const;

               /**
               Get the thread frame function pointer
               @return ThreadFrameFunctionPtr pointer to instance
               or default thread frame
               */

      virtual  ThreadFrameFunctionPtr  getFramePointer( void );

               /// Get the stack pointer

               BytePtr  getStack( void );

               /// Get the top of stack pointer

               BytePtr  *getStackTop( void );

      //
      // Mutators
      //

               /**
               Change the sharing mask for the thread. This is
               only effective when set prior to starting the
               thread.
               @param Int mask of values for thread resource sharing
               and signal disposition
               */

               void  setShareMask( Int );

               /**
               Allows the caller to substitute the thread frame
               entry point.
               @param ThreadFrameFunctionPtr points to the new frame
               function that is called when starting a thread.
               If this argument is NULLPTR the default handler
               is set.
               */

               void setFrameFunction( ThreadFrameFunctionPtr );

               /**
               Allows the caller to substitute the routines which create
               and destroy the managed ThreadContext object. The 
               call to create the object comes in at the startThread 
               prior to stack allocation, the call to destroy  the object
               comes from startThread exception and error handling, or
               when requested by the caller.
               @param ThreadContextCreatePtr the function pointer to 
               set, If this argument is NULLPTR the default 
               handlers are set for create and destroy.
               @param ThreadContextDestroyPtr to the function pointer to set. 
               If this argument is NULLPTR the default handlers are set 
               for create and destroy.
               */

               void  setContextFunctions
                  (
                     ThreadContextCreatePtr ,
                     ThreadContextDestroyPtr 
                  );

               /**
               Allows the caller to substitute the routines which create
               and destroy the managed ThreadContext stack object. The 
               call to create the stack object comes in at the startThread 
               prior to threading, the call to destroy  the object
               comes from startThread exception and error handling, or
               when the destruction of the ThreadContext is imanent.
               @param ThreadStackCreatePtr pointer to set. If this
               argument is NULLPTR the default handlers are set for create 
               and destroy.
               @param ThreadStackDestroyPtr the function pointer to set.
               If this argument is NULLPTR the default handlers are set 
               for create and destroy.
               */

               void  setStackFunctions
                  (
                     ThreadStackCreatePtr ,
                     ThreadStackDestroyPtr 
                  );


               /**
               Set the return code for the thread
               @param Int return code value
               */

               void  setReturnCode( Int );

               /**
               Set the state for the thread
               @param ThreadState the threads new state
               */

               void  setThreadState( ThreadState );

               /**
               The definitive thread frame entry point. This is the
               address that "clone" gets. 
               @param ThreadContext pointer to a thread context
               @return Int return code
               */

      static   Int   cloneFrameFunction( ThreadContextPtr );

      //
      // Factory invocations
      //

               /**
               Create a instance of ourself, we also invoke
               the create stack method so the instance is
               ready to be used to run a thread.
               @return ThreadContext pointer to object.
               @exception ThreadAllocationException either
               for Stack or Context
               */

               ThreadContextPtr  createContext( void ) 
                  throw ( ThreadException );

               /**
               Destroys the context instance. A check is made
               to insure it is not a suicide.
               @param ThreadContext pointer to context to destroy
               @exception Assertion if self referenced
               */

               void  destroyContext( ThreadContextPtr ) throw ( Assertion );

   protected:

      //
      // Constructors
      //
                        /// Default constructor throws NEVER_GET_HERE

                        ThreadContext( void ) throw ( Assertion );

      //
      // Operator overloads
      //

               /**
               Assignment operator for designating thread
               identity
               @param ThreadIdentifier as retrieved from the
               OS
               @return ThreadContext reference to self
               */

               ThreadContextRef  operator=( ThreadIdentifier );

      //
      // Accessors
      //

               /**
               Return the function pointer of the callers thread
               routine.
               @return CallerFunctionPtr
               */

               CallerFunctionPtr    getCallerFunction( void );

   private:

      //
      // Mutators
      //

               /**
               The default thread frame entry point. This is the
               address that the immutableFrameFunction gets and calls
               either the defaultFrameFunction or user specified
               entry point.
               @param ThreadContext pointer to a thread context
               @return Int return code
               */
               
      static   Int   defaultFrameFunction( ThreadContextPtr );

      //
      // Factory methods
      //

               /**
               The default allocation routine for the managers ThreadContext.
               The copy constructor is called with the argument reference
               @param ThreadContext reference to the context supplied in the
               startThread method.
               @return The newly allocated managed context
               */

      static   ThreadContextPtr  defaultContextCreate( ThreadContextRef );

               /**
               The default destroyer of managed ThreadContexts.
               @param ThreadContext pointer to managed object.
               */

      static   void  defaultContextDestroy( ThreadContextPtr );

               /**
               The default allocation routine for the threads stack.
               @param ThreadContext pointer to the managed context.
               @return Byte pointer to bottom of stack.
               */

      static   BytePtr  defaultStackCreate( ThreadContextPtr );

               /**
               The default destroyer of managed ThreadContext stacks.
               @param ThreadContext pointer to managed object
               */

      static   void     defaultStackDestroy( BytePtr );


   private:

               /// The default thread frame entry point

      static   ThreadFrameFunctionPtr  theDefaultFrameFunction;

               /// The default context create factory method

      static   ThreadContextCreatePtr  theDefaultContextCreator;

               /// The default context destroy factory method

      static   ThreadContextDestroyPtr theDefaultContextDestroyer;

               /// The default stack create factory method

      static   ThreadStackCreatePtr    theDefaultStackCreator;

               /// The default stack destroy factory method

      static   ThreadStackDestroyPtr   theDefaultStackDestroyer;

               /// The assigned thread frame entry point

               ThreadFrameFunctionPtr  theFrameFunction;
         
               /// The assigned context create factory method
         
               ThreadContextCreatePtr  theContextCreator;
         
               /// The assigned context destroy factory method
         
               ThreadContextDestroyPtr theContextDestroyer;
         
               /// The assigned stack create factory method
         
               ThreadStackCreatePtr    theStackCreator;
         
               /// The assigned stack destroy factory method
         
               ThreadStackDestroyPtr   theStackDestroyer;

               /// Non-adjust stack pointer

               BytePtr              theStack;      

               /// Stack size in bytes

               Size                 theStackSize;

               /// Shared resource flags

               Int                  theShareMask;

               /// Unique thread identifier

               ThreadIdentifier     theThreadIdentifier;

               /// Caller thread entry point

               CallerFunctionPtr    theCallersFunction;

               /// State of thread

               ThreadState          theThreadState;

               /// Return code from theCallersFunction

               Int                  theReturnCode;
   };

}

#endif // if !defined(__THREADCONTEXT_HPP)

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.1 $
   $Date: 2000/04/23 20:43:13 $
   $Locker:  $
*/

