|
Real-time software sometimes involves handling parallel interactions with
multiple entities to initiate some action. Further action can be initiated only
after response message has been received from all the entities. Parallel Wait
state pattern handles such scenarios.
The figure below shows a typical parallel operation. Here A initiates a
parallel operation by sending a request to B, C and D. B, C and D perform the
operation in parallel and respond back to A.

Intent
The main intention here is to initiate similar activity on multiple entities
in parallel. Since activities are initiated in parallel, the time taken to
perform the task is more or less independent of the number of entities involved
in the interaction. This is faster in comparison to Serial Wait State pattern
where one message is sent to initiate an activity on an entity, its response is
awaited and only on receipt of the response same activity is initiated on the
next entity.
The main objective of this design pattern is to efficiently handle scenarios
where sending of similar message to multiple entities to initiate similar
activity in parallel is involved. Here, a response is expected from each entity
after the entity finishes the activity. This also involves counting the received
response messages and recognizing the point where collection has been completed.
Also Known As
- Simultaneous Action State Pattern
- Parallel Interaction
Motivation
Main motivation to use Parallel Wait State is to speed up operations with
multiple entities. If a particular operation takes a long time to perform,
initiating the operation in parallel will be the most time efficient way of
performing that operation. Such designs scale very well with increase in number
of entities handled by the system.
Applicability
The Parallel Wait State pattern can be used wherever multiple operations need
to be initiated on multiple entities. This pattern can be applied when parallel
operation does not cause an undue loading of the systems. This design pattern
should not be used in scenarios where each operation is extremely resource
intensive and parallel operation might consume too many system resources at the
same time.
Structure
This pattern consists of the following event handlers:
- Parallel Message Sending Routine: This
routine sends message to multiple entities in one shot. This routine also
starts a timer to keep track of parallel response collection.
- Parallel Response Handler: This
handler receives the response messages being collected and takes a decision
when collection has been completed. The collection is assumed to have been
completed, when the parallel response count matches the number of requests
sent to multiple entities.
- Timeout Handler: When a timeout takes
place, the parallel message sending routine calls this handler. If the
parallel response count is less than the number of messages sent, timeout signals failure of
response message collection. Otherwise, timeout signals a successful
response message collection. Depending on requirement, the timeout handler
retries by resending the command message to the entity that timed out and
keeps a timer to await the response.
Participants
The key participants in this pattern are the task sending the message to
multiple entities and the tasks on these entities that receive this command
message, perform the desired operation and send back the response message.
Collaboration
The state machine implementing the parallel state pattern collaborates with
the tasks on the entities where some desired operation needs to be performed.
The state machine keeps a timer to keep track of the operation being performed
at each entity.
Consequences
Parallel state pattern can result in triggering a state transition
corresponding to successful collection of response messages. If a timeout takes place
before the collection of response messages has been completed, a state transition to an error
handling state might be initiated.
Implementation
Implementing the Parallel Wait State Pattern involves sending request
messages in parallel and waiting till all responses are collected. The
implementation sequence is illustrated by the following example based on digital
trunk diagnostics.
In the Xenon switching system XEN Configuration Manager
(XCM) needs to initiate diagnostics on all the digital trunk circuits controlled
by the XEN. This is done by sending diagnostics request message to all the circuits and
waiting for response from each circuit. Once the responses are received from all the
circuits, XCM responds back to the initiator.
- Parallel Wait State is invoked to start diagnostics on all the digital
trunks in the XEN.
- Parallel Wait State loops through the list of digital trunk circuits and
sends a diagnostics request to each circuit. A timer is initiated to wait
for diagnostics response. A counter is incremented to keep track of number
of requests.
- The diagnostics progress in parallel and the digital trunk cards respond
back on completion of diagnostics.
- The Parallel Wait State receives the responses from all the digital trunk. It
decrements the counter when a response is successfully received.
- When the counter goes down to zero, all responses have been received, so
the aggregate response can be sent back.
Sample Code and Usage
Here is the sample code for the digital trunk diagnostics example:
| Digital
Trunk Diagnostics Using the Parallel Wait State Pattern |
class CPerformingDiagnosticsState : public CState
{
int m_nOutstandingRequests; // Count of outstanding diagnostics requests
public:
// Send out the diagnostics requests
void InitiateDiagnostics(CStateMachine &m)
{
DigitalTrunk *pTrunk;
m_nOutstandingRequests = 0;
for (int i=0; i < DIGITAL_TRUNK_COUNT; i++)
{
// Obtain a pointer to the digital trunk
pTrunk = m.GetDigitalTrunk(i);
// Send the diagnostics request to this trunk
m.SendDiagnosticsRequest(pTrunk->GetTrunkId());
// Update Trunk State
pTrunk->SetState(AWAITING_DIAGNOSTICS);
// Keep track of outstanding requests
m_nOutstandingRequests++;
}
// Starting a single timer to keep track of responses
StartTimer();
}
// Handle Diagnostics Response
void OnDiagnositcsResponse(CStateMachine& m, const DiagnosticsResponse* pMsg)
{
DigitalTrunk *pTrunk = m.GetDigitalTrunk(pMsg->GetTrunkId());
// Check if the response has been received from a valid terminal in a valid state
if (pTrunk->GetState() != AWAITING_DIAGNOSTICS)
{
// No response is awaited from this terminal, so ignore the response
return;
}
// Save the diagnostics status
m.m_diagnosticsStatus[pMsg->GetTrunkId()] = pMsg->GetDiagnosticsStatus();
ASSERT (m_nOutstandingCount > 0);
// One less response is outstanding.
if (--m_nOutstandingRequests == 0)
{
// All responses have been received so stop the timer
StopTimer();
// Now respond back with the status of all diagnostics responses
m.SendCollectedDiagnosticsResponse(m.m_diagnositsStatus);
// Going back to Idle State
m.ChangeState(pIdleState);
}
}
// Handle Timeout
virtual void OnTimeout(CStateMachine& m)
{
TRACE("Response Missed from %d Digital Trunks\n", m_nOutstandingRequests);
// Respond back whatever responses were received.
m.SendCollectedDiagnosticsResponse(m.m_diagnositsStatus);
// Going back to Idle State
m.ChangeState(pIdleState);
}
};
|
Known Uses
This design pattern has been used in the following cases:
- Initiating diagnostics on multiple entities
- Parallel initialization of multiple modules during system
initialization.
- Polling of multiple entities in parallel
Related Patterns
|