-
-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathServiceSM.h
More file actions
315 lines (262 loc) · 10.2 KB
/
Copy pathServiceSM.h
File metadata and controls
315 lines (262 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
//==============================================================================
//
// ServiceSM.h
//
// Copyright (C) 2013-2025 Greg Utas
//
// This file is part of the Robust Services Core (RSC).
//
// RSC is free software: you can redistribute it and/or modify it under the
// terms of the Lesser GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// RSC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the Lesser GNU General Public License
// along with RSC. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef SERVICESM_H_INCLUDED
#define SERVICESM_H_INCLUDED
#include "Pooled.h"
#include <cstddef>
#include "Event.h"
#include "EventHandler.h"
#include "Q1Way.h"
#include "SbTypes.h"
#include "Trigger.h"
namespace SessionBase
{
class AnalyzeMsgEvent;
}
//------------------------------------------------------------------------------
namespace SessionBase
{
// ServiceSM is the base class for the run-time instance of a SessionBase
// application. Each application defines a subclass to support a run-time
// instance of its state machine. A modifier of a root service subclasses
// from ServiceSM, whereas a root service (non-modifier) subclasses from
// RootServiceSM.
//
class ServiceSM : public NodeBase::Pooled
{
friend class NodeBase::Q1Way<ServiceSM>;
friend class Event;
friend class SbInitiationReq;
friend class SsmContext;
public:
// Initial state for SSMs. If an SSM is in this state at the end of
// a transaction, it is destroyed. A modifier in this state does not
// receive SAPs, SNPs, or SIPs.
//
static const StateId Null = 1;
// Returns the Context on which the SSM is running.
//
virtual SsmContext* GetContext() const;
// Returns the port (local PSM identifier) associated with the message
// to be analyzed. The PSM on which the message arrived is available
// as ame.Msg()->Psm(). Before it performs its own analysis, a modifier
// should invoke its parent's CalcPort function, and a subclass should
// invoke its base class CalcPort function.
//
virtual ServicePortId CalcPort(const AnalyzeMsgEvent& ame) = 0;
// Handles an SAP for a modifier SSM. The default version returns
// EventHandler::Pass and must be overridden by a modifier that needs
// to observe its parent's behavior after being initiated.
//
virtual EventHandler::Rc ProcessSap(Event& currEvent, Event*& nextEvent);
// Handles an SNP for a modifier SSM. The default version returns
// EventHandler::Pass and must be overridden by a modifier that needs
// to observe its parent's behavior after being initiated.
//
virtual EventHandler::Rc ProcessSnp(Event& currEvent, Event*& nextEvent);
// Returns the service identifier associated with this SSM.
//
ServiceId Sid() const { return sid_; }
// Returns the service associated with this SSM.
//
Service* GetService() const;
// Returns the SSM's current state.
//
StateId CurrState() const { return currState_; }
// Returns the SSM's next state.
//
StateId NextState() const { return nextState_; }
// Sets STID as the SSM's next state. May be overridden for observation
// purposes, but the base class version must be invoked.
//
virtual void SetNextState(StateId stid);
// Informs the SSM that exPsm is being deleted. The default version
// informs modifiers of the PSM deletion. May be overridden to clear
// PSM pointers in member data, for example, but the base class version
// must be invoked.
//
virtual void PsmDeleted(const ProtocolSM& exPsm);
// Returns true if the SSM has entered the Null state.
//
bool HasIdled() const { return idled_; }
// Returns a modifier's parent SSM. Returns nullptr for a root SSM.
//
ServiceSM* Parent() const { return parentSsm_; }
// Sets SAP as the SSM's next service alteration point. May be
// overridden for observation purposes, but the base class version
// must be invoked.
//
virtual void SetNextSap(TriggerId sap);
// Sets SNP as the SSM's next service notification point. May be
// overridden for observation purposes, but the base class version
// must be invoked.
//
virtual void SetNextSnp(TriggerId snp);
// Returns true if the trigger identified by TID has completed its
// initiator processing.
//
bool HasTriggered(TriggerId tid) const;
// Sets sid_ to SID. This has the effect of replacing the SSM's
// current states, triggers, and event handlers with those defined
// by SID. If both sets of event handlers can use the same SSM,
// the change will be transparent.
//
virtual void MorphToService(ServiceId sid);
// Overridden to obtain an SSM from its object pool.
//
static void* operator new(size_t size);
// Overridden to display member variables.
//
void Display(std::ostream& stream,
const std::string& prefix, const NodeBase::Flags& options) const override;
// Overridden to enumerate all objects that the SSM owns.
//
void GetSubtended(std::vector<Base*>& objects) const override;
// Overridden to select SSMs by ServiceId and StateId.
//
bool Passes(uint32_t selector) const override;
// Overridden for patching.
//
void Patch(sel_t selector, void* arguments) override;
protected:
// Modifier SSMs are created by Service::AllocModifier. Non-modifier SSMs
// subclass from RootServiceSM. Protected because this class is virtual.
//
explicit ServiceSM(ServiceId sid);
// Invoked by EndOfTransaction if the SSM is in the Null state. Deletes
// any modifiers in the SSMQ and any events in an event queue. Protected
// to restrict deletion. Virtual to allow subclassing.
//
virtual ~ServiceSM();
// Invoked at the end of each transaction. Traverses the SSMQ to invoke
// this function on each modifier. Deletes the SSM if it is in the Null
// state. May be overridden to release resources before deletion, but
// the base class version must be invoked.
//
virtual void EndOfTransaction();
private:
// Handles an initiation ack for a modifier SSM that was just created.
// The default version kills the context and must be overridden.
//
virtual EventHandler::Rc ProcessInitAck
(Event& currEvent, Event*& nextEvent) = 0;
// Handles an initiation nack for a modifier SSM that was just created.
// The default version kills the context and must be overridden if the
// modifier's initiation request can be denied.
//
virtual EventHandler::Rc ProcessInitNack
(Event& currEvent, Event*& nextEvent);
// Handles an SIP for a modifier SSM. The default version returns
// EventHandler::Pass and must be overridden by a modifier that needs
// to observe the initiation of a sibling.
//
virtual EventHandler::Rc ProcessSip(Event& currEvent, Event*& nextEvent);
// Steps within the function ProcessEvent.
//
enum Phase
{
ModifierSapPhase, // pass the event's SAP down the SSMQ
ModifierReentryPhase, // reenter the SSMQ upon a EventHandler::Resume
InitiatorSapPhase, // pass the event's SAP down the InitQ
InitiatorReentryPhase, // reenter the InitQ upon a EventHandler::Resume
LocalEventPhase, // pass the event to the context SSM, and then
// pass the event's SNP down the SSMQ and InitQ
FreeEventPhase // free the event
};
// Enqueues EVT on the queue associated with LOC.
//
void EnqEvent(Event& evt, Event::Location loc);
// Exqueues EVT from the queue associated with LOC.
//
bool ExqEvent(Event& evt, Event::Location loc);
// Coordinates the event handling phases for currEvent. nextEvent is
// the next event to be processed, if any.
//
EventHandler::Rc ProcessEvent(Event* currEvent, Event*& nextEvent);
// Used during error recovery.
//
EventHandler::Rc EventError2(Event*& evt, EventHandler::Rc rc) const;
// Sets a modifier's parent.
//
void SetParent(ServiceSM& parent);
// Adds MODIFIER at the front of the SSMQ.
//
void HenqModifier(ServiceSM& modifier);
// Routes an SAP down this SSM's SSMQ, starting at MODIFIER.
//
EventHandler::Rc ProcessSsmqSap
(ServiceSM* modifier, Event& sapEvent, Event*& nextEvent, Phase& phase);
// Routes an SAP down TRIGGER's Initiator queue, starting at MODIFIER.
//
EventHandler::Rc ProcessInitqSap
(const Trigger* trigger, const Initiator* modifier, Event& sapEvent,
Event*& nextEvent, Phase& phase);
// Routes an SNP down this SSM's SSMQ, starting at MODIFIER.
//
void ProcessSsmqSnp(ServiceSM* modifier, Event& snpEvent);
// Routes an SNP down TRIGGER's Initiator queue, starting at MODIFIER.
//
void ProcessInitqSnp
(const Trigger* trigger, const Initiator* modifier, Event& snpEvent);
// Routes an SIP down this SSM's SSMQ.
//
EventHandler::Rc ProcessInitReq
(Event& currEvent, Event*& nextEvent, Phase& phase);
// Used during error recovery.
//
void EventError1(Event*& evt) const;
// Deletes the SSM if it is a modifier in the Null state.
//
void DeleteIdleModifier();
// The service identifier associated with this SSM.
//
ServiceId sid_;
// The SSM's current state.
//
StateId currState_;
// The SSM's next state.
//
StateId nextState_;
// Set if the SSM has entered the Null state.
//
bool idled_;
// The next SAP to be processed.
//
TriggerId nextSap_;
// The next SNP to be processed.
//
TriggerId nextSnp_;
// Set if an SAP has completed its routing down the InitQ.
//
bool triggered_[Trigger::MaxId + 1];
// The queue of modifiers.
//
NodeBase::Q1Way<ServiceSM> ssmq_;
// The parent SSM, if this SSM is a modifier.
//
ServiceSM* parentSsm_;
// The events currently owned by the SSM.
//
NodeBase::Q1Way<Event> eventq_[Event::Location_N];
};
}
#endif