#ifndef _aplmt_itc_smboxapi_h_
#define _aplmt_itc_smboxapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: ITC Simple Mailbox Interfaces (SMBOX)
**
** DESCRIPTION:
**  This file provides the interface for delivering and receiving ITC messages. 
**  The following descriptions assumes that the reader is familiar with general 
**  concepts of inter-thread-communications. 
**
**  CAUTION: The mailbox handle function arguments are NOT type-safe. The 
**           implementation actually defines the handles as void pointers. This
**           is done because each mailbox is/can be different sizes, which 
**           translates to different types. Given the different types, the
**           two choices were 1) require the applicaiton to always cast the
**           handles to a 'generic' mailbox handle type; or 2) pass the
**           the handles as void pointers.  Since both approaches are bad
**           with respect to type safety, option 2 was choosen because it
**           is "easier" on the developer.
**
**  SMBOX vs. IMBOX
**  ---------------
**  This interfaace (SMBOX) is alternate ITC mailbox paradigm.  It is much 
**  simpler than the IMBOX/IMSG interfaces, but it also imposes hard limits
**  on the size of the mailboxes.  What this means, is that when a client
**  'posts a message' there is the possibility that the post operation fails
**  because the mailbox queue if full.  NOTE: Both the SMBOX and IMBOX 
**  interaces can be 'mixed' within a single application - JUST BE SURE YOU 
**  KNOW WANT YOU DOING. 
**  
**  MAILBOXES:
**  ----------
**  A mailbox is a pre-allocated FIFO queue that can hold N messages, and 
**  functions as the delivery mechanism for ITC messages.  Mailboxes are 
**  logically bound to threads.  Mailboxes are automatically bound to the 
**  thread of the caller of Aplmt_smboxReceive().  Technically, the 
**  'binding' last on for during of call, so it is possible to change the 
**  'binding' of mailbox on every call to Aplmt_smboxReceive(). 
**  HOWEVER, it is strongly recommended that the application binds a given 
**  mailbox to one and only thread. 
**
**  TIMEOUTS:
**  ---------
**  The default implementation of the mailbox method: Aplmt_smboxReceive() 
**  waits indefinitely 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_smboxReceiveTimeout(), 
**  that takes a timeout parameter.  
**
**  MESSAGES:
**  ---------
**  Messages are a single data item/type that are passed by value.  The 
**  default implementation is all messages are void pointers.  There is 
**  no interpretation of the messages by this interface.  The message type 
**  is fixed at compile type, so the data type for all messages for all 
**  mailboxes are the same.
** 
**  SIGNALLING
**  ----------
**  By default the SMBOX mailbox is not signal-able like the IMBOX is.
**  However, there is compile switch, USE_APLMT_SMBOX_SUPPORT_SIGNALING, 
**  that allows the SMBOX mailbox to be signaled.  The difficulty arises in 
**  that the SMBOX function semantics do not support the ability to inform the 
**  application that the mailbox was signaled.  The signal indication takes
**  on the form of a special message ID/Handle - which also means that the 
**  range of message ID/handles becomes restricted.  The application can
**  use the option, OPTION_APLMT_SMBOX_WAS_SIGNALED, to customize the what
**  the signaled-message ID is.
** 
**  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.  
**  However, the application can not use the thread-semaphore to receive 
**  aysnchronous signals. 
**
**  FOOTPRINT:
**  ----------
**  For determining the RAM usage of a mailbox, the following C struct is
**  functionally equilivant to the actual implementation.
**      struct SMailbox
**          {
**          AplmtThreadHdl        _myThread;
**          AplRingBuf<type,size> _msgs;    // type:=message type, size:=max number of queued msgs.
**          };
**
**  USAGE:
**  ------
**  The mailbox FIFO queue is implemented a fixed-size Ring buffer.  Each 
**  mailbox instance can have a different size ring buffer.  The following 
**  snippet shows how to define, allocate, and use a SMBOX mailbox.
**
**      // Define, allocate, and initialize a mailbox
**      APLMT_STRUCTDEF_SMBOX(MailboxFoo,MAX_MSGS_FOR_FOO);  
**      struct MailboxFoo mboxFoo;
**      Aplmt_smboxInit( &mboxFoo, MAX_MSGS_FOR_FOO);
**
**      // Post a message to the mail box 
**      void* msg = <pointer to my message data>;
**      Aplmt_smboxSend( &mboxFoo, msg );
**  
**      // Get the next available message from the mailbox    
**      void* nextmsg;
**      nextmsg = Aplmt_smboxReceive( &mboxfoo );
**
**
**
** CONFIGURATION 
** -------------
**  COMPILE:        USE_APLMT_SMBOX_SUPPORT_SIGNALING
**                  USE_APLMT_SMBOX_WITH_TIMEOUT                          
**                                            
**  APPLICATION:    The application can override the following types/defintions
**                      AplmtSmboxMsg
**                      AplmtSmboxQueueSize
**                      OPTION_APLMT_SMBOX_WAS_SIGNALED
**
**  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


/*-------------- MACROS ----------------------------------------------------*/
/** Helper macros for defining a mailbox type that can hold at most 'N'
    messages.
 */
#define APLMT_STRUCTDEF_SMBOX(structName,N)   _APLMT_STRUCTDEF_SMBOX(structName,N)


/*-------------- CONSTANTS -------------------------------------------------*/
/** NULL Mailbox Handle. */
#define APLMT_NULL_SMBOX_HANDLE             _APLMT_NULL_SMBOX_HANDLE

/** Message ID and/or Handle that indicates that the mailbox was signaled
    (note: there is no actual message in this case).
 */
#ifndef OPTION_APLMT_SMBOX_WAS_SIGNALED
#define OPTION_APLMT_SMBOX_WAS_SIGNALED     ((AplmtSmboxMsg)-1)
#endif

/*-------------- TYPES -----------------------------------------------------*/
/** FIFO Queue size.  This data type represents the maximum 'buffer offset'
    and/or max number of elements in the FIFO.  The default limits the
    the mailboxes to 255 messages.  NOTE: This type is used for all
    mailboxes.
*/
#ifndef AplmtSmboxQueueSize
#define AplmtSmboxQueueSize                 AplByte
#endif 


/** Handle to a GENERIC/Sizeless mailbox */
#define AplmtSmboxHdl                       struct AplmtSmbox*

/** Message Type. */
#ifndef AplmtSmboxMsg
#define AplmtSmboxMsg                       void*
#endif

/*-------------- INLINE IMPLEMENTATION -------------------------------------*/
#include "aplmt/itc/smbox.h"            /* For: inline implementation */


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method is used to initalize the 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.  See
          the 'USAGE' above for example of how to define, allocate,
          and initialize the mailbox.
        o Data types: struct AplmtSmbox* == AplmtSmboxHdl.  The application 
          must provide an actual INSTANCE, not just a pointer, to the mailbox
          being initialized.
        o CAUTION: make sure that the size parameter 'maxMessages' is the
          same value that was used in the 'APLMT_STRUCTDEF_SMBOX' statement.

    Prototype:
        void Aplmt_smboxInit( struct AplmtSmbox* mboxToInit, AplmtSmboxQueueSize maxMessages )
 */
#define Aplmt_smboxInit                     _Aplmt_smboxInit


/*-------------- 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').  The method returns non-zero (true) if the message was 
    successfully inserted in the mailbox's FIFO queue.  If the queue is
    full, zero (false) is returned.

    Prototype:
        AplBool Aplmt_smboxSend( AplmtSmboxHdl destMbox, AplmtSmboxMsg msg );
 */
#define Aplmt_smboxSend                     _Aplmt_smboxSend

/** This method is the same as Aplmt_smboxSend(), except that it can be called
    from an interrupt service routine.  

    Prototype:
        AplBool Aplmt_isr_smboxSend( AplmtSmboxHdl destMbox, AplmtSmboxMsg msg );
 */
#define Aplmt_isr_smboxSend                 _Aplmt_isr_smboxSend

/** 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.
    NOTES:
        o This method is only available if the compile option,
          USE_APLMT_SMBOX_SUPPORT_SIGNALING, was specified.

    Prototype:
        void Aplmt_smboxSignal( AplmtSmboxHdl destMbox );
 */
#define Aplmt_smboxSignal                   _Aplmt_smboxSignal

/** This method is the same as Aplmt_smboxSignal(), except that it can 
    be called from an interrupt service routine.
    NOTES:
        o This method is only available if the compile option,
          USE_APLMT_SMBOX_SUPPORT_SIGNALING, was specified.

    Prototype:
        void Aplmt_isr_smboxSignal( AplmtSmboxHdl destMbox );
 */
#define Aplmt_isr_smboxSignal               _Aplmt_isr_smboxSignal

/** 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 next/currently
    received message.  

    Prototype:
        AplmtSmboxMsg Aplmt_smboxReceive( AplmtSmboxHdl mbox );
 */    
#define Aplmt_smboxReceive                 _Aplmt_smboxReceive

/** This method is the same as Aplmt_smboxReceive(), except the method 
    will timeout and/or return after the specified time interval (in 
    milliseconds) if a message was not received.  The retrieved message is
    returned via the function parameter 'retrievedMsg'. The method returns
    non-zero (true) if a message was retrieved.  Zero (false) is returned
    if the timeout period expired before a message was received. BY DEFAULT 
    THIS METHOD IS DISABLED.  It must be enabled by the application
    using the compile switch: USE_APLMT_SMBOX_WITH_TIMEOUT.
    NOTES:
        o If APLMT_WAIT_NO_TIMEOUT is specified as the timeout period, 
          the method behaves exactly the same as Aplmt_smboxReceive(),
          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: This method is dependent on Aplmt_waitThreadTimeout()
          which is OPTIONAL.  Check your platform's documentation before using
          this method.
          
    Prototype:
        AplBool Aplmt_smboxReceiveTimeout( AplmtSmboxHdl mbox, AplmtSmboxMsg* retrievedMsg, AplSize_t maxWaitInMilliseconds )
 */
#define Aplmt_smboxReceiveTimeout          _Aplmt_smboxReceiveTimeout



#ifdef __cplusplus
}
#endif
/*--------------------------------------------------------------------------*/
#endif  /* end _aplmt_itc_smboxapi_h_ */
