Publish-Subscriber Design Patterns in Embedded Systems

来源:百度文库 编辑:神马文学网 时间:2024/07/05 19:11:29
Publish-Subscribe Design Patterns
Local Publish-Subscriber Design Pattern Documentation
Remote Publish-Subscriber Design Pattern Documentation
While developing embedded system, one frequently encounters a situation wheremany entities are interested in occurrence of a particular event. Thisintroduces a strong coupling between the publisher and subscriber of this eventchange notification. Thus whenever a new entity needs the information, code forthe publisher of the information also needs to be modified to accommodate thenew request.
An Example
Consider the example of a system which manages terminals. Here many entitieswould be interested in knowing when a terminal's status changes. A few examplesare:
Call Processing module needs to know when the terminal goes out of service so that calls on the terminal can be cleared.
Alarm processing software needs to know of terminal status change, so that alarms can be raised/cleared.
Resource manager would be interested in terminal status change as it needs to change the resource counts when terminal status changes.
As the design progresses, more and more applications would be interested instatus change. Its easy to see that this complicates the design, asterminal status handling has to be modified on each occasion.
Publish-Subscribe Pattern
The Publish-Subscribe Pattern solves the tight coupling problem. Here thecoupling is removed by the publisher of information supporting a genericinterface for subscribers. Entities interested in the information subscribe tothe publisher by registering for the information. With this interface, thepublisher code does not need to be modified every time a subscriber isintroduced.
Whenever information needs to be published, the publisher invokes the Publishmethod to inform all the subscribers.
This pattern comes in two flavors:
Local Publish-Subscribe Pattern: Use this pattern when publisher and all the subscribers are a part of the same task.
Remote Publish-Subscribe Pattern: This pattern should be used when publisher and subscribers are implemented in different tasks/processors. All communication takes place via messages.
Here we develop the LocalStatusPublisher class.This class can be used as a helper class when this generic subscribe-publishinterface is desired. The following important public methods are supported:
PublishStatus: Invoke this method to inform all registered subscribers about status change.
Register: Invoke this method to register an object for the status change notification.
Deregister: Invoke this method to deregister an object. The object will not receive any notifications of status change after it deregisters.
Local Status Publisher
00009 #include "Subscriber.h" 00010 #include 00033 00035 { 00036 enum { 00038NOT_FOUND = -1, 00039 00041MAX_SUBSCRIBERS = 100 00042 }; 00045 ]; 00047 0005600057 intFind(Subscriber *pSubscriber) const 00058 { 00059 int index =NOT_FOUND; 00060 for (int i=0; i HandleStatusChange(unitId, status); 00093 } 00094 } 00095 } 0010700108OperationStatusRegister(Subscriber *pSubscriber) 00109 { 00110OperationStatus status = FAILURE; 00111 // First check if the subscriber is already present 00112 // in the list 00113 int index =Find(pSubscriber); 00114 00115 if (index ==NOT_FOUND) 00116 { 00117 // Subscriber was not found, so this is not a duplicate request 00118 // Now look for a free entry by finding NULL 00119 index =Find(NULL); 00120 if (index !=NOT_FOUND) 00121 { 00122 // A free entry has been found 00123m_pSubscriber[index] = pSubscriber; 00124 status = SUCCESS; 00125 } 00126 } 00127 return status; 00128 } 0012900138OperationStatusDeregister(Subscriber *pSubscriber) 00139 { 00140OperationStatus status = FAILURE; 00141 // Search for the entry 00142 int index =Find(pSubscriber); 00143 if (index !=NOT_FOUND) 00144 { 00145 // Free the entry by marking as NULL 00146m_pSubscriber[index] = NULL; 00147 status = SUCCESS; 00148 } 00149 return SUCCESS; 00150 } 00151 00152 };
Here we will look at the RemoteStatusPublisherclass. This class supports a message based interface. Subscribers sendregistration request message to register for the status change. The sourceaddress of the sender is saved as a part of the registration process.Deregistration request is sent to stop receiving the status change notifications.
Whenever status change is detected, PublishStatusmethod is invoked. This method sends the status change message to all theregistered subscribers using the address that was obtained during registration.
Remote Status Publisher
00009 #include "Subscriber.h" 00010 #include 0001100013 typedef unsigned longSubscriberAddress; 0001400016 structRegisterRequestMessage 00017 {00019 intopcode; 0002000022SubscriberAddresssubscriberAddress; 00023 }; 0002400026 structDeregisterRequestMessage 00027 {00029 intopcode; 0003000032SubscriberAddresssubscriberAddress; 00033 }; 0003400036 enumOperationStatus {SUCCESS, FAILURE}; 0003700039 enumAckType {REGISTRATION_ACK, DEREGISTRATION_ACK}; 0004000063 classRemoteStatusPublisher 00064 { 00065 enum { 00066 00068FREE_ENTRY = 0, 00069 00071NOT_FOUND = -1, 00072 00074MAX_SUBSCRIBERS = 100 00075 }; 0007600079SubscriberAddressm_subscriberAddress[MAX_SUBSCRIBERS]; 0008600087 intFind(SubscriberAddress subscriberAddress) const 00088 { 00089 int index =NOT_FOUND; 00090 for (int i=0; i subscriberAddress); 00144 00145 if (index ==NOT_FOUND) 00146 { 00147 // Subscriber was not found, so this is not a duplicate request 00148 // Now look for a free entry by finding FREE_ENTRY 00149 index =Find(FREE_ENTRY); 00150 if (index !=NOT_FOUND) 00151 { 00152 // A free entry has been found 00153m_subscriberAddress[index] = pMsg->subscriberAddress; 00154 status = SUCCESS; 00155SendRequestStatus(pMsg->subscriberAddress, REGISTRATION_ACK , status); 00156 } 00157 } 00158 } 0015900165 voidHandleDeregisterRequest(constDeregisterRequestMessage *pMsg) 00166 { 00167OperationStatus status = FAILURE; 00168 // Search for the entry 00169 int index =Find(pMsg->subscriberAddress); 00170 if (index !=NOT_FOUND) 00171 { 00172 // Free the entry by marking as FREE_ENTRY 00173m_subscriberAddress[index] =FREE_ENTRY; 00174 status = SUCCESS; 00175 } 00176 00177 // Inform the requester with an acknowledgement. 00178SendRequestStatus(pMsg->subscriberAddress, DEREGISTRATION_ACK,status); 00179 } 00180 00181 };
Explore More ...
Local Publish-Subscriber Design Pattern Documentation
Remote Publish-Subscriber Design Pattern Documentation