Introduction
Event-driven programming or event-based programming is a programming paradigm in which the flow of the program is determined by events, i.e., sensor outputs or user actions (mouse clicks, key presses) or messages from other programs or threads.
Event-driven applications usually are organized as in state machine modes due to complicated event interaction. An IPC event queue manager is required to support event-based programming.
Interactive with Service Providers
Event-driven applications may operate with lower layer software modules or hardware interfaces, which are called service providers. A service is formally specified by a set of primitives (operations) available to service users (applications). These primitives tell the service to perform some action or report on an action taken by a peer component/entity. The service primitives are classified into four categories:
- Request
- Indication
- Response
- Confirm
[Computer Networks, Andrew S.Tanenbaum]. The request and confirm primitives can be implemented in the form of service calls. The indication and response primitives can be implemented in the form of external event posting.
Active state machine objects can communicate with service providers using one of the following mechanisms for exchanging information:
- Synchronous service calls. These synchronous service calls may block, returning control to the application when the operation completes. Since most real-time systems must respond to external events in a predetermined amount of time, synchronous service calls are not used.
- Asynchronous service calls. Asynchronous functions do not block, continuing execution and returning before the operation is completed.
- Pro-active event indications. These events are posted from a service component to a client component without any request. An example might be an event posted by a hardware interrupt service routine.
Platform-Independent Application Development
There are many different Operation Systems or hardware in the embedded system market. Each different OS provides a different API to access a set of common system services. The OS Virtual Layer provides a platform independent adapter layer allowing state machine portability between different operating systems.
IPC Event Manager
The IPC Shared Memory can be used to share information between different processes. However, in practical engineering, a source process may request to send an event to a destination process and not return until the event is received by the destination process. Or, post an event to a destination process, which just leaves the event at a queue, and returns immediately. The destination process then queries the available events and takes specific actions based on event types.
An IPC event queue manager is required to support synchronous event handling and asynchronous event handling.
Using the Code
Class XSharedMemoryQueue
This manages a set of shared memory queues. Each queue is a double linked list. The class contains a set of queue headers pointing to these queues. When an instance of the class is created, all queue nodes are linked at the first queues. Other queues are empty.
class XSharedMemoryQueue
{
public:
XSharedMemoryQueue();
~XSharedMemoryQueue();
bool Initialize (const char* strMapName, int iNodeSize,
int iNodeCount, int iQueueCount);
void Release ();
void* CreateSharedMemoryQueue ();
void DeleteSharedMemoryQueue ();
void* OpenSharedMemoryQueue ();
void CloseSharedMemoryQueue ();
void* GetAt(int iIndex);
int GetIndex(void* pNode);
void* GetQueueHead(int iQueue);
void* GetQueueTail(int iQueue);
void* GetNext(void* pNode);
void* GetPrev(void* pNode);
bool MoveToDestQueueTail(void* pNode, int iDestQueue);
int LocateQueue(void* pNode);
void DumpQueue (int iQueue, bool bDumpNode);
void DumpNode (void* pNode);
private:
char* m_strMapName;
int m_iNodeSize; int m_iNodeCount; int m_iQueueCount; int* m_pQueueArray; shared_memory_t m_hMapMem;
void* m_pMappedPointer;
};
-
bool XSharedMemoryQueue:: Initialize (const char* strMapName,
int iNodeSize, int iNodeCount, int iQueueCount);
Initializes a set of shared memory queues. Initialize()
defines the object name, the shared memory queue count, the queue node size, and the number.
-
void*XSharedMemoryQueue::CreateSharedMemoryQueue ();
Creates a set of shared memory queues. The function in the Windows edition creates a named file mapping object. The function in the Linux edition creates a shared memory object. For inter-process communication, the master process calls this function to create a set of shared memory queues.
-
void XSharedMemoryQueue::OpenSharedMemoryQueue ();
Opens a set of shared memory queues. The function in the Windows edition opens an existing named file mapping object. The function in the Linux edition opens an existing shared memory object. For inter-process communication, the slave processes call this function to create a set of shared memory queues.
-
void XSharedMemoryQueue::DeleteSharedMemoryQueue ();
Deletes a set of shared memory queues. The function in the Windows edition deletes a named file mapping object. The function in the Linux edition deletes a shared memory object. For inter-process communication, the master process calls this function to delete a set of shared memory queues.
-
void XSharedMemoryQueue::CloseSharedMemoryQueue ();
Closes a set of shared memory queues. The function in the Windows edition closes an existing named file mapping object. The function in the Linux edition closes an existing shared memory object. For inter-process communication, the slave processes call this function to close a set of shared memory queues.
-
void * XSharedMemoryQueue::GetQueueHead(int iQueue);
Returns the header of a given queue.
-
void * XSharedMemoryQueue::GetQueueTail(int iQueue);
Returns the tail of a given queue.
-
void * XSharedMemoryQueue::GetNext(void* pNode);
Returns the next item of a queue node.
-
void * XSharedMemoryQueue::GetPrev(void* pNode);
Returns the previous item of a queue node.
-
bool MoveToDestQueueTail(void* pNode, int iDestQueue);
Removes the given node from the source queue and adds this node to the destination queue. If the destination queue is empty, the node is added as the head of the queue. If the destination queue is not empty, the node is appended to the destination queue.
Structure IPCEventInfo
Defines the structure of an inter-process communication event information.
Class XExtIPCEvent
Manipulates a set of shared memory queues to send or post an event to a destination process.
There are three shared memory queues defined in the enum.
{IPC_QUEUE_RESOURCE=0,IPC_QUEUE_SENDING=1,IPC_QUEUE_POSTING=2};
IPC_QUEUE_RESOURCE
is an IPC event block pool. IPC_QUEUE_SENDING
is an IPC event queue where events in the queue are in the process of sending. IPC_QUEUE_POSTING
is an IPC event queue where events in the queue are going to be posted.
struct IPCEventInfo
{
int SourceProcessID;
int DestProcessID;
int IPCEventStatus;
int EventID;
unsigned long ulParameter1;
unsigned long ulParameter2;
};
typedef int (*SME_IPC_EVENT_CALLBACK_T)(void* pInEventInfo);
class XExtIPCEvent
{
public:
XExtIPCEvent();
~XExtIPCEvent();
enum {IPC_EVENT_BUFFER_SIZE=1024};
enum {IPC_QUEUE_NUMBER=4};
enum {IPC_QUEUE_RESOURCE=0,IPC_QUEUE_SENDING=1,IPC_QUEUE_POSTING=2};
enum TmCommandStatus
{
EVENT_STATUS_UNUSED = 0, EVENT_STATUS_SENDING,
EVENT_STATUS_POSTING,
EVENT_STATUS_CONSUMED
};
static XExtIPCEvent* GetInstance ();
int Initialize (int ProcessID, bool bIsMasterProcess = false);
void Release (bool bIsMasterProcess = false);
int SendIPCEvent(IPCEventInfo* pInEventInfo,
IPCEventInfo* pOutEventInfo,
int nTimeout = -1);
int PostIPCEvent(IPCEventInfo* pInEventInfo);
int QueryIPCEvent(IPCEventInfo* pOutEventInfo,
SME_IPC_EVENT_CALLBACK_T pfnCallbak);
void RecycleEvent(int idProcess);
bool DumpInfo ();
private:
int Lock ();
int UnLock();
private:
XSharedMemoryQueue* m_pSMQueue;
XSemaphore* m_pSem;
int m_idProcess;
};
-
int XExtIPCEvent::Create (int ProcessID, bool bIsMasterProcess = false);
Creates an instance of XSharedMemoryQueue
with the process ID and master process information.
-
int XExtIPCEvent::SendIPCEvent(IPCEventInfo* pInEventInfo,
IPCEventInfo* pOutEventInfo, int nTimeout = -1);
Sends an IPC event to a destination process. The function will not return until the event is received by the destination process.
-
int XExtIPCEvent::PostIPCEvent(IPCEventInfo* pInEventInfo);
Posts an IPC event to the post queue and returns immediately.
-
int XExtIPCEvent::QueryIPCEvent(IPCEventInfo* pOutEventInfo,
SME_IPC_EVENT_CALLBACK_T pfnCallbak);
The IPC event recipient process calls this function to query the IPC event.
-
void XExtIPCEvent::RecycleEvent(int idProcess);
Recycles events to the event pool which are sent by the given process, or when the destination process is the given process.
Points of Interest
This is a component of the Open Source project, StateWizard, a ClassWizard-like round-trip UML dynamic modeling/development tool. You may download other components at http://www.intelliwizard.com/.