#ifndef _aplmt_kernelapi_h_
#define _aplmt_kernelapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: Basic Kernel/Thead Interfaces (KRN)
**
** DESCRIPTION:
**  This file provides the interface for the most basic kernel/threading 
**  operations.  
**
**  ABOUT THREAD FACTORIES - Thread factories are great tools for creating
**  threads with a no knowledge about the platform/OS.  However, the 
**  concept gets complicated when it comes to deleting/destorying threads.  
**  The biggest issue with thread factories is deleting threads and how to 
**  reclaim the memory from the defunct threads.  Dependening on the 
**  underlying OS/Kernel, it may or may not be possible to build a thread 
**  factory that does not leak memory.  The standard workaround is not to 
**  delete/destory threads once they are created (duh ;-).  There are several 
**  approaches for mimicking the behaviour of dynamic threads without actually 
**  physically destroying them in between 'uses'.
**
**  DO I HAVE TO USE THE THREAD FACTORY INTERFACE?  Yes and no.  If you want make 
**  your code as platform independent as possible, then yes.  If you don't care
**  about platform independence, or you have sufficiently isolate the 'creator'
**  poritions of your of code, then the answer is maybe.  The multi-thread
**  interfaces defined by the APL library include the concept of a thread-
**  semaphore.  For OS/Kernels do not natively support thread-semaphores, this
**  functionality must be provided by platform specific APL code.  To implement
**  thread-semaphores externally to the OS/Kernel requires the use of thread 
**  specific storage for each thread.  So to summarize, if the underlying
**  OS/kernel does NOT natively support thread-semaphores, then the use of
**  thread factory inteface IS REQUIRED.  If your OS/Kernel provides direct 
**  support for thread-semaphore, then use of thread factory interface is 
**  OPTIONAL.  
**  
**  NOTE:  There is a platform independent alternative to thread factories.  
**         Thread Worker Pool Interface can be used as a poor-man's thread 
**         factory (i.e. when the platform's kernel does not deal well 
**         with recycling threads).  The caveat is that the Thread Worker 
**         Pool approach only works if the order of thread creation is well 
**         defined and/or known.  See the header file: src/aplmt/os/workerapi.h
**         for more details.
**  
**
** CONFIGURATION 
** -------------
**  COMPILE:        none.
**                                            
**  APPLICATION:    none.
**
**  PLATFORM:       Data Types:    
**                      PLATFORM_APLMT_THREADHDL_T
**                      PLATFORM_APLMT_THREADPRIORITY_T
**                      PLATFORM_APLMT_THREADFACHDL_T
**                      PLATFORM_APLMT_THREADENTRY_T
**                      PLATFORM_APLMT_CBFUNCTHREADLIST_T
**
**                  Definitions:
**                      PLATFORM_APLMT_THREADSTATE_WAITING        
**                      PLATFORM_APLMT_THREADSTATE_READY          
**                      PLATFORM_APLMT_THREADSTATE_READY_SIGNALED 
**                      PLATFORM_APLMT_NULL_THREAD_HANDLE 
**                      PLATFORM_APLMT_WAIT_NO_TIMEOUT
**
**
**  NOTES:
**  1. Unless explicitly stated otherwise, NONE of the following methods may be 
**     called from interrupt service routines.
**  2. Unless explicitly stated otherwise, NONE of the following methods may be 
**     called before the platform's kernel is running.
**  3. Unless explicitly stated otherwise, all of the following methods ARE 
**     thread-safe.
**  4. For efficency/optimization some methods are 'inlined'.  The inlining
**     is done by using the preprocessor/macros.  The application should
**     treat all methods as function calls and not rely on the fact they may
**     be currently defined as macros.
----------------------------------------------------------------------------*/


#include "apl/types/types.h"        /* For: basic types */


#ifdef __cplusplus
extern "C" {
#endif



/*-------------- CONSTANTS -------------------------------------------------*/
/** The following are intial states to be used when initializing threads.
 */
#define APLMT_THREADSTATE_WAITING           PLATFORM_APLMT_THREADSTATE_WAITING        
#define APLMT_THREADSTATE_READY             PLATFORM_APLMT_THREADSTATE_READY          
#define APLMT_THREADSTATE_READY_SIGNALED    PLATFORM_APLMT_THREADSTATE_READY_SIGNALED 

/** NULL Thread Handle */
#define APLMT_NULL_THREAD_HANDLE            PLATFORM_APLMT_NULL_THREAD_HANDLE 

/** Used to indicate no-timeout/infinite wait when using wait-with-timeout 
    method (is required to be largest possible wait time for the timeout
    mechanism). 
 */
#define APLMT_WAIT_NO_TIMEOUT               PLATFORM_APLMT_WAIT_NO_TIMEOUT

/** Maximum 'valid' timeout for wait-with-timeout method */
#define APLMT_WAIT_MAX_TIMEOUT              (APLMT_WAIT_NO_TIMEOUT-1)


/*-------------- TYPES -----------------------------------------------------*/
/** Thread Handle/Identifier */
#define AplmtThreadHdl                      PLATFORM_APLMT_THREADHDL_T

/** Thread Priority */
#define AplmtThreadPriority                 PLATFORM_APLMT_THREADPRIORITY_T
                       
/** Handle to a thread Factory */
#define AplmtThreadfacHdl                   PLATFORM_APLMT_THREADFACHDL_T

/** Thread entry function */
#define AplmtThreadEntry                    PLATFORM_APLMT_THREADENTRY_T

/** Callback function for walking the thread list */
#define AplmtCBFuncThreadList               PLATFORM_APLMT_CBFUNCTHREADLIST_T


/*-------------- INLINE PLATFORM IMPLEMENTATION ----------------------------*/
#include "platform/kernelapi.h"       


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method returns non-zero (true) if the underlying kernel/RTOS/OS is 
    running.  
    NOTES: 
        o If the method returns true, it does not necessarily mean that the 
          current thread/context was created via Aplmt_createThread().
        o If the method return false, it does not necessarily mean that 
          interrupts are currently disabled (though typically it does, 
          but is it not guarantied by this interface).

    Prototype:
        AplBool Aplmt_isKernelRunning(void);
 */
#define Aplmt_isKernelRunning                   _Aplmt_isKernelRunning

/** This method defines an interface for a thread factory for creating
    threads. The method returns the handle to the new created thread or
    NULL if there was an error (i.e. out-of-memory).

    DETAILS:
    --------
    Naming:
        The specified 'threadName' must be a null terminated string.  If the 
        specified string exceeded the maximum length of the platform, it will 
        be truncated. 

    Priority:
        Priorities range from 0 to N, where N is dependent on the underlying
        OS.  Zero is the highest priority, N is the lowest.

    Entry Function:
        The entry function must have the following function signature: 
            void myEntryFunction(void* args);

    Thread Arguments:
        Data and/or parameter(s) can be passed to a thread when it is 
        created through the 'args' function argument.  'Args' is a 
        pointer to 'something', which is defined by the application.
        If no thread parameters are needed, set 'args' to zero.

    Thread and Stack Memory:
        The specified 'threadFactoryToUse' is responsible for providing any/all
        of the client supplied memory required by the platform's OS/Kernel.

    Initial states:
        The application is allowed to set the initial state of the thread's
        thread semaphore.  By controlling the state of the thread semaphore,
        the application can control how a thread is 'started'.

        READY                - The thread will run immediately upon creation
                               assuming it is the highest priority thread ready 
                               to run.
        READY/SIGNALED       - The same as READY except that the FIRST time 
                               the thread calls Aplmt_waitThread(), the thread will 
                               NOT block.
        WAITING              - The thread will not run until some other thread
                               signals its thread semaphore.

    Maximum Number of Threads
        The maximum number of threads is factory and/or platform dependent.

    Thread Handles:
        Thread handles are NOT guaranteed to be unique over time.  As
        threads are created and deleted over time a newly create thread
        may have the same thread handle as a thread that previously existed.
        Thread handles are only guaranteed to be unique with respect
        to the current set of active/created threads.  

    Prototype:
        AplmtThreadHdl Aplmt_createThread
            ( 
            AplmtThreadfacHdl   threadFactoryToUse,
            const char*         threadName,
            AplmtThreadPriority priority, 
            AplmtThreadEntry    start, 
            void*               args, 
            AplByte             initialState
            );
 */
#define Aplmt_createThread                      _Aplmt_createThread
                 

/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method causes the current thread to yield control of the CPU and 
    wait on the thread's thread-semaphore.

    Prototype:
        void Aplmt_waitThread(void);
 */
#define Aplmt_waitThread                        _Aplmt_waitThread

/** This method is the same as Aplmt_waitThread(), except the method will 
    timeout and/or return after the specified time interval (in milliseconds), 
    if the thread was not signaled.  The method normally returns non-zero 
    (true).  It only returns 0 (false) if the thread 'waited' on the 
    thread-semaphore and the timeout period expired before the thread was 
    signaled.
    NOTES:
        o If APLMT_WAIT_NO_TIMEOUT is specified as the timeout period, 
          the method behaves exactly the same as Aplmt_waitThread(), i.e. 
          nevers times-out.
        o The longest timeout period is APLMT_WAIT_MAX_TIMEOUT.
        o If 0 is specified as the timout period, then the call acts
          as a 'polled' operation on the thread-semaphore in that it will 
          never block even if the thread-semaphore is not currently signaled
          when called.
        o CAUTION: Do not assume that since the method returned false due to 
          a time-out, that the thread-semaphore is not signaled (i.e. its 
          count is zero).  It is possible that the thread is/was signaled 
          after the 'time-out', BUT before the application has an opportunity
          to check the return code.
        o This method is consider OPTIONAL, i.e. the underlaying platform
          is NOT REQUIRED to support this method.  CHECK YOUR Platform's
          documentation before using this method.

    Prototype:
        AplBool Aplmt_waitThreadTimeout( AplSize_t maxWaitInMilliseconds )
 */
#define Aplmt_waitThreadTimeout                 _Aplmt_waitThreadTimeout

/** This method signals the specified thread's thread-semaphore and causes 
    thread to become unblocked and/or ready to run. 
    Prototype:
        void Aplmt_signalThread( AplmtThreadHdl threadToSignal );
 */
#define Aplmt_signalThread                      _Aplmt_signalThread

/** This method is same as Aplmt_signalThread(), except that it can ONLY be called
    from the context of an interrupt service routine.
    Prototype:
        void Aplmt_isr_signalThread( AplmtThreadHdl threadToSignal );
*/ 
#define Aplmt_isr_signalThread                  _Aplmt_isr_signalThread



/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method returns the handle of the currently running thread. 
    Prototype:
        AplmtThreadHdl Aplmt_getCurrentThread(void);
 */
#define Aplmt_getCurrentThread                  _Aplmt_getCurrentThread

/** This method returns the thread's priority, and thread name of the 
    specified thread.  The method will return false if the specified
    thread does not exists.  
    NOTES: 
        o The caller must supply the memory for storing the returned
          thread priority and thread name. 

    Prototype:
        AplBool Aplmt_getThreadInfo( AplmtThreadHdl       thread, 
                                     AplmtThreadPriority* threadPriority,
                                     char*                nameBuffer,
                                     AplSize_t            nameBufferSize
                                   );
 */
#define Aplmt_getThreadInfo                     _Aplmt_getThreadInfo

/** This method provide a mechanism for walking the platform's list of 
    currently create threads.  The specified callback function is called once 
    for every created thread.  The callback routine can prematurely terminate 
    the traversal by returning false, else true to continue the traversal. 
    During the callback, the application may call the Aplmt_getThreadInfo() 
    methods to get more details about each thread. 
    
    The function signature of the callback is:
        AplBool myCallback( AplmtThreadHdl nextThreadHandle );

    NOTES: 
        o Thread scheduling may be temporarily suspended until the 
          traversal is completed.  So be careful/prudent on how much time 
          you spend in the callback routine.
        o There is NO guaranteed order to the traversal - only that all
          created threads will be reported.
        o DO NOT, repeat DO NOT, create or delete any threads directly 
          or indirectly from the callback routine.
        o The IDLE and SYSTEM threads may or may not be reported.  This
          is platform dependent.

    Prototype:
        void Aplmt_walkThreadList( AplmtCBFuncThreadList callbackFunc );
 */
#define Aplmt_walkThreadList                    _Aplmt_walkThreadList



#ifdef __cplusplus
}
#endif
/*--------------------------------------------------------------------------*/
#endif  /* end _aplmt_kernelapi_h_ */
