#ifndef _aplmt_itc_imboxapi_h_
#define _aplmt_itc_imboxapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: Inter-Thread Communications Mailbox Interfaces (IMBOX)
**
** DESCRIPTION:
**  This file provides the interface for delivering ITC messages. The following
**  descriptions assumes that the reader is familiar with general concepts of 
**  inter-thread-communications. 
**
**  TERMS:
**  ------
**  Client        - The orginator (i.e. source) of an ITC transaction.
**  Server        - The recipient (i.e. destination) of an ITC transaction.
**  Transaction   - An ITC transaction starts with a client posting a message
**                  and ends the delivery of the message to a server.
**  Request       - The client posts a message to a server.  At this point the
**                  client gives up ownership of the message and should not
**                  access the message until it receives the server's response.
**  Response      - The server provides an 'acknowlegement' to the client that 
**                  originated the message request, that the server has received
**                  and/or relinquished ownership of the client's message.
**                  request.
**  Post          - The process of inserting a message into an ITC mailbox.
**  Delivery      - The process of extracting a message from an ITC mailbox.
**  Asynchronous  - The client does not wait/block for the server to complete
**                  its processing.
**  Synchronous   - The client waits/block until the server has generated its
**                  response.
**  
**
**  MODELS:
**  -------
**  The APL IMSG/IMBOX interfaces supports four 'models' of ITC.  The 
**  different models allows the application to select/use what functionality
**  it needs, while minimizing the RAM/ROM footprint of the ITC engine. The
**  four models are (listed in order of the smallest footprint):
**      XSMALL  - Request messages only.  The client has to poll for the
**                server's response.
**      SMALL   - Request and Response messages.
**      NORMAL  - Same as 'SMALL' with the added ability for the client to 
**                post messages synchronously.
**      LARGE   - Same as 'NORMAL' except the application is responsible
**                for allocating the mailboxes and messages.   
** 
**
**  MESSAGES:
**  ---------
**  Messages are unique and there is NO support for 'broadcasting' messages.  
**  What this means, is that once a client has claimed ownership of a message
**  it can not be used by another client until the original client has
**  released ownership (i.e. after recieving the server's response). In 
**  addition, for models XS, S, and N ALL messages and message data fields 
**  are statically allocated.  The application can control how many messages 
**  are allocated and how many messages contain data at compile time.  
**
**
**  MESSAGE DATA:
**  -------------
**  All request messages can be data-less or have data associated with them. 
**  The application determines the mix of data-less vs. data messages. Repsonse
**  message are a little different.  Repsonse message can ONLY have data 
**  associated with them if their corresponding request message has a data 
**  field.  This restriction is because the request/response message pairs
**  SHARE the same data field.  If the server needs to return data to the 
**  client, the client's original request message MUST have a data field.
**
**
**  MAILBOXES:
**  ----------
**  A mailbox is basically a FIFO queue that is used as the storage and 
**  delivery mechanism for ITC messages.  Mailboxes are logically bound to 
**  threads.  Mailboxes are automatically bound to the thread of the caller 
**  of Aplmt_imboxGetNextMessage().  Technically, the 'binding' last on for
**  during of call, so it is possible to change the 'binding' of mailbox
**  on every call to Aplmt_imboxGetNextMessage(). HOWEVER, it is strongly
**  recommended that the application binds a given mailbox to one and only
**  thread. 
**
**  Mailboxes do NOT have limit on how many messages they can store and/or 
**  queue. Additionally, for models XS, S, and N all mailboxes are statically 
**  allocated.  The application can control how many mailboxes are allocated 
**  at compile time.
**
**  Mailboxes have an additional feature in that they can be 'signaled'.  This
**  feature allows mailboxs to receive messages AND support the thread-
**  semaphore semantics at the same time.
**
**
**  TIMEOUTS:
**  ---------
**  The default implementation of the mailbox method: Aplmt_imboxGetNextMessage() 
**  waits indefinitely until until a message arrives.  There is an OPTIONAL
**  (read as not supported by all platforms) compile switch that enables
**  an additional get-next-message method: Aplmt_imboxGetNextMessageTimeout(), 
**  that takes a timeout parameter.  
**
**
**  THREAD-SEMAPHORE
**  ----------------
**  The ITC engine use the OS layer's thread-semaphore as its synchronization 
**  primitive.  The ITC engine use the thread-semaphore intelligently, in that
**  application can still use the thread-semaphore for 'synchronous' operations.  
**  In fact, this is exactly how the ITC engine implements synchronous ITC 
**  calls.  
**  RULE: Do NOT asynchronous signal a thread's thread-semaphore when the
**        thread 'has' a mailbox. 
**  NOTE: Mailboxes have a 'signalling' interface, so the application can (in
**        most cases) substitute signalling the thread's mailbox in place of 
**        signalling the thread's thead-semaphore.
**
**
**  LIMITS:
**  -------
**  When using the LARGE model, the number of messages and mailboxes
**  are only limited by the amount of available RAM. The message ID field
**  for the LARGE model is of type Apl16u.  The following are the limits 
**  for messages and mailboxes when using models: XSMALL, SMALL, and NORMAL
**
**      Item                 Data Type       Data Type Size      Limit   
**      -------------------  ---------       --------------      -----   
**      Maximum messages**   AplmtImsgHdl    Apl8u  (default)      254   
**                                           Apl16u              65533   
**      Maximum mailboxes    AplmtImboxHdl   Apl8u  (default)      254   
**                                           Apl16u              65533
**
**      **Note: This the number of TOTAL messages. For models S,N: the ITC
**              engine automagically creates RESPONSE messages, thus 
**              'consuming' half the total possible range for message IDs.  
**              However, it is possible by using the config switches (see 
**              imsgapi.h) to fine tune/limit how many 'message slots' get 
**              allocated for response messages.  The default setting is to 
**              allocate a RESPONSE message for every 'message'.
**
**
**  LARGE MODEL:
**  ------------
**  The major change for the LARGE model is that the mailbox and message 
**  handles are pointers to structs, instead of indexes into statically 
**  allocated arrays.  This has the following benefits/side effects:
**  o The application is responsible for allocating the memory for all
**    mailbox instances. It is also responsible for initialize each 
**    individual mailbox.
**  o Each client is responsible for allocating and identifying its 
**    own message(s).
**  o A given message is both a request and response message. It is
**    the message's ID field that indicates/marks it as a request or
**    response.  In addition, the client is required to initialize and set 
**    the message's ID field EACH time (and before) it post a message.
**  o A message instance can have a different message ID each time
**    the client posts it.
**  o Messages are compatible with the ILNODE inteface so that the 
**    application can use the Single-Linked List interface for managing 
**    messages (see the apl/containers directory for details about the list 
*     interfaces).
**  o The range of message IDs is 0 to 0x7FFE.  However, message IDs
**    are only required to be unique by their respective destination
**    servers. For example: If the messages sent to Server-A are never
**    sent to Server-B and vis-versus, then the message IDs for the two 
**    sets of messages IDs can overlap.
**  o None the IMSG application options, OPTION_APLMT_IMSG_xxxx, have
**    any meaning and/or effect. 
**  o None the IMBOX application options, OPTION_APLMT_IMBOX_xxxx, have
**    any meaning and/or effect. 
**  o The application can not/does not override the types: AplmtImboxHdl and
**    AplmtImsgHdl. The application can still define/override the AplmtImsgData 
**    type.
**  o There is no error checking regardless of the compile switch.
**  o RAM Usage: The size of a LARGE model message is noticeably bigger than
**    the other models.  However, when you factor in how client's manage
**    message memory in the LARGE model, the overall RAM usage can be smaller 
**    than when using the other models.  This is due to the fact that most 
**    clients send many different messages, but typically only have one or two
**    messages outstanding at any one time.  Since in the LARGE model,
**    messages can be 'reused', a client only needs to allocate memory for
**    maximum number of message(s) it can have outstanding at any one time.
** 
** 
**  FOOTPRINT:
**  ----------
**  For determining the RAM usage of a mailbox, the following C struct is
**  functionally equilivant to the actual implementation.
**      struct IMailbox
**          {
**          AplmtThreadHdl     _myThread;
**          AplmtImsgHdl       _msgListHeadPointer;
**          AplmtImsgHdl       _msgListTailPointer;
**          AplByte            _flags;
**          };
**
**  For determining the RAM usage of a message, the following C struct is
**  functionally equilivant to the actual implementation.
**      struct IMessage
**          {
**          AplmtImsgHdl       _listPointer;       // Used by the mailboxes to implement their FIFO queues
**          AplmtImsgData      _payload;           // ONLY applies to messages that 'HAVE' data and/or LARGE model
**          AplmtImboxHdl      _responseMbox;      // ONLY applies if using models: SMALL, NORMAL, LARGE
**          AplmtThreadHdl     _syncClientThread;  // ONLY applies if using models: NORMAL, LARGE
**          AplmtImsgId        _messageID;         // ONLY applies if using models: LARGE
**          };
**
**
**  ERROR CHECKING:
**  ---------------
**  The default configuration has no error checking and/or validation of of 
**  message and mailbox handles/identifiers.  When error checking is enable, all
**  function calls attempt to valid their respective input data.  If an 
**  error and/or invalid value is detected a FATAL ERROR will be generated.  To
**  enable error checking use the switch USE_APLMT_ITC_INCLUDE_ERROR_CHECKING. 
**
**
** CONFIGURATION 
** -------------
**  COMPILE:        USE_APLMT_ITC_MODEL_XSMALL
**                  USE_APLMT_ITC_MODEL_SMALL
**                  USE_APLMT_ITC_MODEL_NORMAL
**                  USE_APLMT_ITC_MODEL_LARGE
**                  USE_APLMT_ITC_INCLUDE_ERROR_CHECKING
**                  USE_APLMT_IMBOX_WITH_TIMEOUT
**                  USE_APLMT_INIT_IMBOX_IN_SYSTEM_INIT
**                                            
**  APPLICATION:    The application can override the following types/defintions
**                      AplmtImboxHdl
**                      OPTION_APLMT_IMBOX_MAX_MAILBOXES
**
**  PLATFORM:       none.
**
**
**  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 "aplcfg.h"                 /* For: Application configuration */
#include "apl/types/types.h"        /* For: basic types */


#ifdef __cplusplus
extern "C" {
#endif


/*-------------- ERRORS ----------------------------------------------------*/
/** An invalid mailbox handle was specified when calling an Aplmt_imboxXXX() 
    method. Note: Error Checking must be enable for this error to occur.
 */
#define APLMT_ERRSTR_IMBOX_INVALID_HANDLE   "IMBOX: A invalid mailbox handle was used when making a all to an IMBOX method."
/***/
#define APLMT_ERR_IMBOX_INVALID_HANDLE      _APLMT_ERR_IMBOX_INVALID_HANDLE


/*-------------- CONSTANTS -------------------------------------------------*/
/** Number of mailboxes (default value) */
#ifndef OPTION_APLMT_IMBOX_MAX_MAILBOXES
#define OPTION_APLMT_IMBOX_MAX_MAILBOXES    8
#endif

/** NULL Mailbox Handle. */
#define APLMT_NULL_IMBOX_HANDLE             _APLMT_NULL_IMBOX_HANDLE

/** Return code for Aplmt_imboxGetNextMessageTimeout() that indicates the
    call timed-out before a message/signal was received.
 */
#define APLMT_IMBOX_GETNEXT_TIMEOUT         _APLMT_IMBOX_GETNEXT_TIMEOUT
    

/*-------------- TYPES -----------------------------------------------------*/
/** Mailbox Handle.  For the models: XS, S, N, the default limits the maximum 
    number of mailboxes to 254 
*/
#ifndef AplmtImboxHdl
#define AplmtImboxHdl                       _AplmtImboxHdl
#endif 


/*-------------- INLINE IMPLEMENTATION -------------------------------------*/
#include "aplmt/itc/iprivate.h"            /* For: inline implementation */


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method is used to initalize the mailbox sub-system.  It must be called
    BEFORE any other Aplmt_imsgXXX() and Aplmt_imboxXXX() methods (except for
    Aplmt_imsgInitialize()).
    NOTES:
        o If USE_APLMT_INIT_IMBOX_IN_SYSTEM_INIT is defined, then APL will
          internally call this method as part of the Aplmt_systemInit()
        o This method has no meaning if the application is using the LARGE
          model (i.e. do not need to call, but if called does nothing).

    Prototype:
        void Aplmt_imboxInitialize(void)
 */
#define Aplmt_imboxInitialize                   _Aplmt_imboxInitialize

/** This method is used to initalize a ITC mailbox.  This method must called
    before the mailbox is first used.  This method should only be called
    once per mailbox.
    NOTES:
        o The application is required allocate/create the mailbox.  Use
          the data type: AplmtImbox to allocate a concrete mailbox instance.
        o Data types: AplmtImbox* == AplmtImboxHdl.  The application must
          provide an actual INSTANCE, not just a pointer, to the mailbox
          being initialized.:
        o This method is ONLY valid/available when using the LARGE model.

    Prototype:
        void Aplmt_imboxInit( AplmtImbox* mboxToInit )
 */
#define Aplmt_imboxInit                         _Aplmt_imboxInit


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method is used by clients to send/post an ITC message to a server.
    The server is identified by the destination mailbox.  It is acceptable
    for the client and server to share the same thread (i.e. post a message 
    to 'myself').

    Prototype:
        void Aplmt_imboxPost( AplmtImboxHdl destMbox, AplmtImsgHdl msg );
 */
#define Aplmt_imboxPost                         _Aplmt_imboxPost

/** This method is the same as Aplmt_imboxPost(), except that it can be called
    from an interrupt service routine.  NOTE: The interrupt service routine
    is REQUIRED to ensure that the message is NOT-IN-USE when calling this
    mesage.

    Prototype:
        void Aplmt_isr_imboxPost( AplmtImboxHdl destMbox, AplmtImsgHdl msg );
 */
#define Aplmt_isr_imboxPost                     _Aplmt_isr_imboxPost

/** This method is used to signal the specified mailbox.  Signalling a
    mailbox has the same semantics as the mailbox waiting on its
    thread's thread-semaphore and the client signalling the waiting
    thread's thread-semaphore.

    Prototype:
        void Aplmt_imboxSignal( AplmtImboxHdl destMbox );
 */
#define Aplmt_imboxSignal                       _Aplmt_imboxSignal

/** This method is the same as Aplmt_imboxSignal(), except that it can 
    be called from an interrupt service routine.

    Prototype:
        void Aplmt_isr_imboxSignal( AplmtImboxHdl destMbox );
 */
#define Aplmt_isr_imboxSignal                   _Aplmt_isr_imboxSignal

/** This method is used by a server to retrieve posted ITC messages.
    This is a blocking call in that if no messages are currently available
    then the calling thread blocks until a new message is received. It is 
    acceptable for the client and server to share the thread (i.e. post a 
    message to 'myself').  The method returns the handle to the next/currently
    received message.  If the mailbox was signaled, then the method returns
    APLMT_NULL_IMSG_HANDLE.  Note: The 'signaled' condition takes precedence
    over queued messages (i.e. the 'signal' state is not queued/sync'd with
    the received message, but is 'delivered' immediately). The following 
    psuedo code demostrates how a 'server thread' should use this method:

        void threadEntryFunction( void* args )
            {
            ....
            for(;;)
                {
                AplmtImsgHdl msg = Aplmt_imboxGetNextMessage( myMailbox )
                switch ( Aplmt_imsgGetId(msg) )
                    {
                    case APLMT_IMSG_SIGNAL_RECEIVED:
                        do_mailbox_was_signaled();
                        break;

                    case MSG_1: 
                        do_msg1_was_received();
                        break;
                    ...
                    case MSG_N: 
                        do_msgN_was_received();
                        break;
                    }
                } 
            }

    Prototype:
        AplmtImsgHdl Aplmt_imboxGetNextMessage( AplmtImboxHdl mbox );
 */    
#define Aplmt_imboxGetNextMessage               _Aplmt_imboxGetNextMessage

/** This method is the same as Aplmt_imboxGetNextMessage(), except the method 
    will timeout and/or return after the specified time interval (in 
    milliseconds) if a message was not received.  Also, there is an additional
    return code, APLMT_IMBOX_GETNEXT_TIMEOUT, that is returned to indicate 
    that the call timed-out (i.e. was not signaled and no message receivied).
    BY DEFAULT THIS METHOD IS DISABLED.  It must be enabled by the application
    using the compile switch: USE_APLMT_IMBOX_WITH_TIMEOUT.
    NOTES:
        o If APLMT_WAIT_NO_TIMEOUT is specified as the timeout period, 
          the method behaves exactly the same as Aplmt_imboxGetNextMessage(),
          i.e. nevers times-out.  See aplmt/os/kernelapi.h for details
          on APLMT_WAIT_NO_TIMEOUT.
        o The longest timeout period is APLMT_WAIT_MAX_TIMEOUT. Again see
          aplmt/os/kernelapi.h for details.
        o If 0 is specified as the timout period, then the call acts
          as a 'polled' operation on the mailbox in that it will never block 
          even if the mailbox is currently empty when called.
        o CAUTION: The application must test the return code for 
          APLMT_NULL_IMSG_HANDLE *and* APLMT_IMBOX_GETNEXT_TIMEOUT before
          calling Aplmt_imsgGetId() (since either one of these return codes
          will crash the system if passed to Aplmt_imsgGetId()).
        o CAUTION: This method is dependent on Aplmt_waitThreadTimeout()
          which is OPTIONAL.  Check your platform's documentation before using
          this method.
          
    Prototype:
        AplmtImsgHdl Aplmt_imboxGetNextMessageTimeout( AplmtImboxHdl mbox, AplSize_t maxWaitInMilliseconds )
 */
#define Aplmt_imboxGetNextMessageTimeout        _Aplmt_imboxGetNextMessageTimeout


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method performs the same function as Aplmt_imboxPost(), except that
    the client will receive a response message/event when the destination 
    server calls Aplmt_imsgReturnToSender() on the posted message.  
    
    Message Identifiers:
        SERVER - The server receives the request message.  The message ID
                 is the message ID that was posted by the client.
        CLIENT - The client recieves the response message.  The message ID
                 is the message ID of original request message arithmetically
                 added with APLMT_IMSG_RESPONSE_ID.  The 'renaming' of the 
                 request message to the corresponding response message is done 
                 automagically and does NOT require any intervention from 
                 the application.

    Data/Payload:
        Request messages can have a data/payload field.  Response messages
        never have a data/payload field.  If the server needs to return
        data to the client, it puts/plants the data in the data/payload
        field of the request message.  Receiveing a response message indicates
        that the client now has ownership of the original request message
        and can safely access the request message's data/payload field.

    Mailboxes. 
        The client thread is REQUIRED to have a mailbox and have a message 
        processing loop just a like server, since when the server generates
        the response message, the server is acting as ITC client, the client 
        that originated the request message is now a server for the ITC 
        response message.

    Arguments:
        requestMbox     - Destination mailbox of the server
        msg             - Message to post
        responseMbox    - Source mailbox of the client issuing the request  
        
    NOTE: This method only has meaning if the application selects the SMALL,
          NORMAL, or LARGE ITC models.

    Prototype:
        void Aplmt_imboxPostRequest( AplmtImboxHdl requestMbox, AplmtImsgHdl msg, AplmtImboxHdl responseMbox );
 */    
#define Aplmt_imboxPostRequest                  _Aplmt_imboxPostRequest


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method peforms the same function as Aplmt_imboxPost(), except that
    the client's thread will block until the destination server calls
    Aplmt_imsgReturnToSender() on the posted message.  The client's thread is 
    NOT required to have mailbox.  However, the client's thread MUST be a 
    different thread from that of the destination server.
    NOTES: 
        o This method only has meaning if the application selects the 
          NORMAL or LARGE ITC models.

    Prototype:
        void Aplmt_imboxPostSync( AplmtImboxHdl destMbox, AplmtImsgHdl msg );
 */
#define Aplmt_imboxPostSync                     _Aplmt_imboxPostSync


#ifdef __cplusplus
}
#endif
/*--------------------------------------------------------------------------*/
#endif  /* end _aplmt_itc_imboxapi_h_ */
