#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 _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 = ; ** 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_ */