|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // generic framework node state machine states |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @publishedPartner |
|
21 @released |
|
22 */ |
|
23 |
|
24 #ifndef SYMBIAN_MM_ACTIVITIES_H |
|
25 #define SYMBIAN_MM_ACTIVITIES_H |
|
26 |
|
27 #include <elements/mm_node.h> |
|
28 #include <elements/mm_nodepeer.h> |
|
29 #include <elements/mm_activities_internal.h> |
|
30 #include <elements/nm_address_internal.h> |
|
31 #include <elements/nm_signatures.h> |
|
32 |
|
33 |
|
34 #ifdef _DEBUG |
|
35 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
36 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
37 _LIT(KSpecAssert_ElemMeshMachActH, "ElemMeshMachActH"); |
|
38 #endif |
|
39 |
|
40 //-========================================================= |
|
41 // |
|
42 // MACROS |
|
43 // |
|
44 //-========================================================= |
|
45 |
|
46 /** |
|
47 Declare and export a node activity. |
|
48 |
|
49 @param name The name of the activity, which will be used to put it into the node's activity map |
|
50 |
|
51 @see DECLARE_NODEACTIVITY |
|
52 */ |
|
53 #define DECLARE_EXPORT_NODEACTIVITY( name ) \ |
|
54 struct name \ |
|
55 { \ |
|
56 IMPORT_C static const MeshMachine::TNodeActivity& Self(); \ |
|
57 IMPORT_C static const NetStateMachine::TStateTriple& FirstTriple(); \ |
|
58 static const MeshMachine::TNodeActivity iSelf; \ |
|
59 static const NetStateMachine::TStateTriple iData[]; \ |
|
60 }; |
|
61 |
|
62 /** |
|
63 Declares a node activity. A node activity is a state machine. It contains multiple nodeactivity |
|
64 entries, which respresent the states, transitions and forks of the state machine. |
|
65 |
|
66 @param name The name of the activity, which will be used to put it into the node's activity map |
|
67 |
|
68 @see DEFINE_NODEACTIVITY |
|
69 @see NODEACTIVITY_ENTRY |
|
70 */ |
|
71 #define DECLARE_NODEACTIVITY( name ) \ |
|
72 struct name \ |
|
73 { \ |
|
74 inline static const MeshMachine::TNodeActivity& Self() {return iSelf;} \ |
|
75 inline static const NetStateMachine::TStateTriple& FirstTriple() {return iData[1];} \ |
|
76 static const MeshMachine::TNodeActivity iSelf; \ |
|
77 static const NetStateMachine::TStateTriple iData[]; \ |
|
78 }; |
|
79 |
|
80 #ifdef SYMBIAN_TRACE_ENABLE |
|
81 /** |
|
82 Define and export a custom node activity. |
|
83 |
|
84 @param id Identifier for the activity |
|
85 @param name The name of the activity |
|
86 @param msgtype Message which will kickoff this activity |
|
87 @param ctor Constructor for the custom activity class |
|
88 |
|
89 @see DEFINE_CUSTOM_NODEACTIVITY |
|
90 */ |
|
91 #define DEFINE_EXPORT_CUSTOM_NODEACTIVITY( id, name, msgtype, ctor ) \ |
|
92 EXPORT_C const MeshMachine::TNodeActivity& name :: Self() {return iSelf;} \ |
|
93 EXPORT_C const NetStateMachine::TStateTriple& name :: FirstTriple() {return iData[1];} \ |
|
94 const MeshMachine::TNodeActivity name :: iSelf = {id, msgtype::EId, msgtype::ERealm, name :: iData[1], &ctor, _S8(#name)}; \ |
|
95 DEFINE_TRIPLES_TABLE( name :: iData ) |
|
96 |
|
97 /** |
|
98 Define a custom node activity. A custom node activity is a node activity which defines its own |
|
99 node activity class. This is used, for example, if the activity wishes to share some custom context |
|
100 information between the states and transition in the activity. |
|
101 |
|
102 Node activity class must derive from CNodeActivityBase. |
|
103 |
|
104 @param id Identifier for the activity |
|
105 @param name The name of the activity |
|
106 @param msgtype Message which will kickoff this activity |
|
107 @param ctor Constructor for the custom activity class |
|
108 |
|
109 @see DEFINE_NODEACTIVITY |
|
110 @see CNodeActivityBase |
|
111 */ |
|
112 #define DEFINE_CUSTOM_NODEACTIVITY( id, name, msgtype, ctor ) \ |
|
113 const MeshMachine::TNodeActivity name :: iSelf = {id, msgtype::EId, msgtype::ERealm, name :: iData[1], &ctor, _S8(#name)}; \ |
|
114 DEFINE_TRIPLES_TABLE( name :: iData ) |
|
115 |
|
116 #else |
|
117 |
|
118 /** |
|
119 Define and export a custom node activity. |
|
120 |
|
121 @param id Identifier for the activity |
|
122 @param name The name of the activity |
|
123 @param msgtype Message which will kickoff this activity |
|
124 @param ctor Constructor for the custom activity class |
|
125 |
|
126 @see DEFINE_CUSTOM_NODEACTIVITY |
|
127 */ |
|
128 #define DEFINE_EXPORT_CUSTOM_NODEACTIVITY( id, name, msgtype, ctor ) \ |
|
129 EXPORT_C const MeshMachine::TNodeActivity& name :: Self() {return iSelf;} \ |
|
130 EXPORT_C const NetStateMachine::TStateTriple& name :: FirstTriple() {return iData[1];} \ |
|
131 const MeshMachine::TNodeActivity name :: iSelf = {id, msgtype::EId, msgtype::ERealm, name :: iData[1], &ctor, NULL}; \ |
|
132 DEFINE_TRIPLES_TABLE( name :: iData ) |
|
133 |
|
134 /** |
|
135 Define a custom node activity. A custom node activity is a node activity which defines its own |
|
136 node activity class. This is used, for example, if the activity wishes to share some custom context |
|
137 information between the states and transition in the activity. |
|
138 |
|
139 Node activity class must derive from CNodeActivityBase. |
|
140 |
|
141 @param id Identifier for the activity |
|
142 @param name The name of the activity |
|
143 @param msgtype Message which will kickoff this activity |
|
144 @param ctor Constructor for the custom activity class |
|
145 |
|
146 @see DEFINE_NODEACTIVITY |
|
147 @see CNodeActivityBase |
|
148 */ |
|
149 #define DEFINE_CUSTOM_NODEACTIVITY( id, name, msgtype, ctor ) \ |
|
150 const MeshMachine::TNodeActivity name :: iSelf = {id, msgtype::EId, msgtype::ERealm, name :: iData[1], &ctor, NULL}; \ |
|
151 DEFINE_TRIPLES_TABLE( name :: iData ) |
|
152 |
|
153 #endif |
|
154 |
|
155 /** |
|
156 Define and declare a custom node activity |
|
157 |
|
158 @param id Identifier for the activity |
|
159 @param name The name of the activity |
|
160 @param msgtype Message which will kickoff this activity |
|
161 @param ctor Constructor for the custom activity class |
|
162 |
|
163 @see DEFINE_CUSTOM_NODEACTIVITY |
|
164 */ |
|
165 #define DECLARE_DEFINE_CUSTOM_NODEACTIVITY( id, name, msgtype, ctor ) \ |
|
166 DECLARE_NODEACTIVITY( name ) \ |
|
167 DEFINE_CUSTOM_NODEACTIVITY( id, name, msgtype, ctor ) |
|
168 |
|
169 /** |
|
170 Define and export node activity |
|
171 |
|
172 @param id Identifier for the activity |
|
173 @param name The name of the activity |
|
174 @param msgtype Message which will kickoff this activity |
|
175 |
|
176 @see DEFINE_NODEACTIVITY |
|
177 */ |
|
178 #define DEFINE_EXPORT_NODEACTIVITY( id, name, msgtype ) \ |
|
179 DEFINE_EXPORT_CUSTOM_NODEACTIVITY( id, name, msgtype, MeshMachine::CNodeActivityBase::NewL ) |
|
180 |
|
181 /** |
|
182 Define the start of a node activity. There must be a matching @c NODEACTIVITY_END to close the |
|
183 node activity. |
|
184 |
|
185 The @c id is a unique identifier for the activity. It allows activities to be overridden in an |
|
186 activity map. When deriving from an activity map, if you specify a node activity in your map |
|
187 whose id is the same as one in the parent map, the one in the parent map with be overriden. |
|
188 |
|
189 The @c name of the activity is used to add it to the activity map. |
|
190 |
|
191 The @c msgtype is the type of message which will initiate this activity. This can be left as the |
|
192 null message, in which case it will be the first state which decides whether to start the activity |
|
193 or not. |
|
194 |
|
195 @code |
|
196 namespace ExampleActivity { |
|
197 DEFINE_NODEACTIVITY(EFoobarActivity, SimpleFoobarActivity, TFoobar) |
|
198 FIRST_NODEACTIVITY_ENTRY(TAwaitingFoobar, TDoOneThingOrAnother) |
|
199 NODEACTIVITY_ENTRY(KDoOneThing, TDoTheThing, TAwaitingResponseToThing, TNoTag) |
|
200 NODEACTIVITY_ENTRY(KAnother, TDoTheOtherThing, TAwaitingResponseToThing, TNoTag) |
|
201 LAST_NODEACTIVITY_ENTRY(KNoTag, TDoFinalThing) |
|
202 NODEACTIVITY_END() |
|
203 } // end namespace ExampleActivity |
|
204 @endcode |
|
205 |
|
206 A node activity must start with either a @c FIRST_NODEACTIVITY_ENTRY or a @c SINGLE_NODEACTIVITY_ENTRY. In |
|
207 the latter case there should be no other entries in the node activity. |
|
208 |
|
209 The activity object (@c CNodeActivityBase) is only created once the second @c NODEACTIVITY_ENTRY is entered. |
|
210 |
|
211 @param id Identifier for the activity |
|
212 @param name The name of the activity |
|
213 @param msgtype Message which will kickoff this activity |
|
214 |
|
215 @see DEFINE_ACTIVITY_MAP |
|
216 */ |
|
217 #define DEFINE_NODEACTIVITY( id, name, msgtype ) \ |
|
218 DEFINE_CUSTOM_NODEACTIVITY( id, name, msgtype, MeshMachine::CNodeActivityBase::NewL ) |
|
219 |
|
220 /** |
|
221 Define and declare a node activity |
|
222 |
|
223 @param id Identifier for the activity |
|
224 @param name The name of the activity |
|
225 @param msgtype Message which will kickoff this activity |
|
226 |
|
227 @see DEFINE_ACTIVITY_MAP |
|
228 */ |
|
229 #define DECLARE_DEFINE_NODEACTIVITY( id, name, msgtype ) \ |
|
230 DECLARE_DEFINE_CUSTOM_NODEACTIVITY( id, name, msgtype, MeshMachine::CNodeActivityBase::NewL ) |
|
231 |
|
232 /** |
|
233 Define an entry in a node activity. |
|
234 |
|
235 @param transitionTag Condition on which the entry is entered |
|
236 @param stateTransition Transition to be executed |
|
237 @param state State to enter after |
|
238 @param stateFork Fork to decide which entry to enter next |
|
239 |
|
240 @see DEFINE_NODEACTIVITY |
|
241 */ |
|
242 #define NODEACTIVITY_ENTRY( transitionTag, stateTransition, state, stateFork ) \ |
|
243 STATE_TRIPLE_ENTRY( transitionTag, stateTransition, state, stateFork ) |
|
244 |
|
245 /** |
|
246 Define the first entry in a node activity |
|
247 |
|
248 @param firstState Initial state of the activity |
|
249 @param firstStateFork Fork to decide which entry to enter next |
|
250 |
|
251 @see DEFINE_NODEACTIVITY |
|
252 */ |
|
253 #define FIRST_NODEACTIVITY_ENTRY( firstState, firstStateFork ) \ |
|
254 FIRST_TRIPLE_ENTRY( firstState, firstStateFork ) |
|
255 |
|
256 /** |
|
257 Define a through entry. Through entries execute a transition but do not |
|
258 enter a state. Instead they move onto the next entry in the node activity |
|
259 using the @c stateFork to decide which entry this is. |
|
260 |
|
261 @param transitionTag Condition on which the entry is entered |
|
262 @param stateTransition Transition to be executed |
|
263 @param stateFork Fork to decide which entry to enter next |
|
264 */ |
|
265 #define THROUGH_NODEACTIVITY_ENTRY( transitionTag, stateTransition, stateFork ) \ |
|
266 THROUGH_TRIPLE_ENTRY( transitionTag, stateTransition, stateFork ) |
|
267 |
|
268 /** |
|
269 Define the final entry in a node activity. |
|
270 |
|
271 @param transitionTag Condition on which the entry is entered |
|
272 @param lastTransition Final transition to be executed |
|
273 |
|
274 @see DEFINE_NODEACTIVITY |
|
275 */ |
|
276 #define LAST_NODEACTIVITY_ENTRY( transitionTag, lastTransition ) \ |
|
277 LAST_TRIPLE_ENTRY( transitionTag, lastTransition ) |
|
278 |
|
279 /** |
|
280 Define a single node activity entry. This is the first and last entry in any |
|
281 node activity in which it is used. |
|
282 |
|
283 @param state Initial state of the activity |
|
284 @param stateTransition Transition to execute once the state is fulfilled |
|
285 |
|
286 @see DEFINE_NODEACTIVITY |
|
287 */ |
|
288 #define SINGLE_NODEACTIVITY_ENTRY( stateTransition, state ) \ |
|
289 STATE_TRIPLE_ENTRY( MeshMachine::KNoTag, stateTransition, state, MeshMachine::TNoTag ) |
|
290 |
|
291 /** |
|
292 Define a routing node activity entry. Routing entries neither execute any |
|
293 transition, nor wait in any state. These are useful only for redirecting the |
|
294 path of execution in the state machine. |
|
295 |
|
296 @param transitionTag Condition on which the entry is entered |
|
297 @param stateFork Fork to decide the next transition to enter |
|
298 */ |
|
299 #define ROUTING_NODEACTIVITY_ENTRY( transitionTag, stateFork ) \ |
|
300 THROUGH_TRIPLE_ENTRY( transitionTag, MeshMachine::TDoNothing, stateFork ) |
|
301 |
|
302 /** |
|
303 Marks the end of a node activity. |
|
304 |
|
305 @see DEFINE_NODEACTIVITY |
|
306 */ |
|
307 #define NODEACTIVITY_END() \ |
|
308 TRIPLES_TABLE_END() |
|
309 |
|
310 |
|
311 |
|
312 /** |
|
313 Declare and export an activity map |
|
314 |
|
315 @param map Name of the activity map |
|
316 @see DECLARE_ACTIVITY_MAP |
|
317 */ |
|
318 #define DECLARE_EXPORT_ACTIVITY_MAP( map ) \ |
|
319 struct map \ |
|
320 { \ |
|
321 IMPORT_C static const MeshMachine::TNodeActivityMap& Self(); \ |
|
322 static const MeshMachine::TNodeActivityMap iSelf; \ |
|
323 static const MeshMachine::TNodeActivityMap::TStaticNodeActivity iData[]; \ |
|
324 }; |
|
325 |
|
326 /** |
|
327 Define and export the activity map |
|
328 |
|
329 @param map Name of the activity map |
|
330 @see DEFINE_ACTIVITY_MAP |
|
331 */ |
|
332 #define DEFINE_EXPORT_ACTIVITY_MAP( map ) \ |
|
333 EXPORT_C const MeshMachine::TNodeActivityMap& map :: Self() {return iSelf;} \ |
|
334 const MeshMachine::TNodeActivityMap map :: iSelf = {map :: iData[0]}; \ |
|
335 const MeshMachine::TNodeActivityMap::TStaticNodeActivity map :: iData[] = { |
|
336 |
|
337 /** |
|
338 Declare an activity map. |
|
339 |
|
340 For example, |
|
341 @code |
|
342 DECLARE_ACTIVITY_MAP(MyNodeActivityMap) |
|
343 @endcode |
|
344 |
|
345 This can then be passed into the constructor of a mesh machine node as follows. |
|
346 |
|
347 @code |
|
348 CMyMeshNode::CMyMeshNode(CConnectionProviderFactoryBase& aFactory) |
|
349 : CCoreConnectionProvider(aFactory, MyNodeActivityMap::Self()) |
|
350 { |
|
351 ... |
|
352 @endcode |
|
353 |
|
354 @param map Name of the activity map |
|
355 */ |
|
356 #define DECLARE_ACTIVITY_MAP( map ) \ |
|
357 struct map \ |
|
358 { \ |
|
359 inline static const MeshMachine::TNodeActivityMap& Self() {return iSelf;} \ |
|
360 static const MeshMachine::TNodeActivityMap iSelf; \ |
|
361 static const MeshMachine::TNodeActivityMap::TStaticNodeActivity iData[]; \ |
|
362 }; \ |
|
363 |
|
364 /** |
|
365 Define an activity map. An activity map is a collection of node activities. The activity map can be |
|
366 based on another activity map or this macro can be used to define a standalone activity map. |
|
367 |
|
368 Once defined an activity map can be passed into the constructor of a node, to define |
|
369 what activities that node is capable of executing. |
|
370 |
|
371 @code |
|
372 DECLARE_DEFINE_ACTIVITY_MAP(MyNodeActivityMap) |
|
373 ACTIVITY_MAP_ENTRY(MyNodeActivities, MyFirstActivity) |
|
374 ACTIVITY_MAP_ENTRY(MyNodeActivities, MySecondActivity) |
|
375 ACTIVITY_MAP_END_BASE(BaseActivities, BaseActivityMap) |
|
376 @endcode |
|
377 |
|
378 @param map Name of the activity map |
|
379 |
|
380 @see ACTIVITY_MAP_END_BASE |
|
381 @see ACTIVITY_MAP_END |
|
382 */ |
|
383 #define DEFINE_ACTIVITY_MAP( map ) \ |
|
384 const MeshMachine::TNodeActivityMap map :: iSelf = {map :: iData[0]}; \ |
|
385 const MeshMachine::TNodeActivityMap::TStaticNodeActivity map :: iData[] = { |
|
386 |
|
387 /** |
|
388 Define and declare an activity map. |
|
389 |
|
390 @param map Name of the activity map |
|
391 |
|
392 @see DEFINE_ACTIVITY_MAP |
|
393 */ |
|
394 #define DECLARE_DEFINE_ACTIVITY_MAP( map ) \ |
|
395 DECLARE_ACTIVITY_MAP(map) \ |
|
396 DEFINE_ACTIVITY_MAP(map) |
|
397 |
|
398 /** |
|
399 Create an entry in an activity map. |
|
400 |
|
401 @param name_space Namespace of the activity |
|
402 @param name Name of the activity |
|
403 |
|
404 @see DEFINE_ACTIVITY_MAP |
|
405 */ |
|
406 #define ACTIVITY_MAP_ENTRY( name_space, name ) &name_space::name::Self, |
|
407 |
|
408 /** |
|
409 Mark the end of an activity map. This macro should be used for standalone activity |
|
410 maps. |
|
411 |
|
412 @see DEFINE_ACTIVITY_MAP |
|
413 */ |
|
414 #define ACTIVITY_MAP_END() \ |
|
415 NULL, \ |
|
416 NULL \ |
|
417 }; |
|
418 |
|
419 /** |
|
420 Mark the end of an activity map. This macro should be used for an activity map based |
|
421 on other activity maps. |
|
422 |
|
423 @param name_space The namespace of the base map |
|
424 @param base_map The name of the base map |
|
425 |
|
426 @see DEFINE_ACTIVITY_MAP |
|
427 */ |
|
428 #define ACTIVITY_MAP_END_BASE( name_space, base_map ) \ |
|
429 NULL, \ |
|
430 (MeshMachine::TNodeActivityMap::TStaticNodeActivity)&name_space::base_map::Self \ |
|
431 }; |
|
432 |
|
433 namespace MeshMachine |
|
434 { |
|
435 /** |
|
436 Base class for all node activity objects. Non custom node activities will use this by default. |
|
437 **/ |
|
438 class CNodeActivityBase : public CBase, |
|
439 public NetInterfaces::AApiExtBase, |
|
440 protected NetStateMachine::ACore, |
|
441 protected NetInterfaces::TInterfaceControl |
|
442 { |
|
443 friend class AMMNodeBase; |
|
444 friend class AContextStore; //to be able access NetStateMachine::ACore |
|
445 friend class AActivitySemaphore; //to be able access NetStateMachine::ACore |
|
446 |
|
447 public: |
|
448 /** |
|
449 Create a new activity. This should never be called by user code. |
|
450 |
|
451 @param aActivitySig Context information about how the activity is to be started |
|
452 @param aNode The node to which this activity will belong. |
|
453 @return A pointer to the new Activity base object. Ownership is transferred. |
|
454 */ |
|
455 IMPORT_C static CNodeActivityBase* NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode ); |
|
456 |
|
457 /** |
|
458 Get the @c id of the activity. |
|
459 @return The activity id of the activity |
|
460 */ |
|
461 IMPORT_C virtual TUint16 ActivityId() const; |
|
462 |
|
463 /** |
|
464 Remove an originator from the originator list. |
|
465 |
|
466 @param aIndex Index of originator to remove |
|
467 */ |
|
468 IMPORT_C void RemoveOriginator(TInt aIndex); |
|
469 |
|
470 /** |
|
471 Check if the activity is running. |
|
472 @return ETrue if the activity is still running, otherwise EFalse. |
|
473 */ |
|
474 IMPORT_C virtual TBool IsIdle() const; |
|
475 |
|
476 /** |
|
477 Put the activity into the idle state. This stops the activity running and notifies the mesh machine that |
|
478 it's ok to delete this activity. |
|
479 */ |
|
480 IMPORT_C virtual void SetIdle(); |
|
481 |
|
482 /** |
|
483 Return the activity signature id of the activity. This may not necessarily be the same as the activity id |
|
484 in the case of parallel activities, where the activity id will be [8 bit unique id|8 bit activity sig] |
|
485 |
|
486 @return The activity signature id |
|
487 */ |
|
488 TUint ActivitySigId() const |
|
489 { |
|
490 return iActivitySig.iId; |
|
491 } |
|
492 |
|
493 /** |
|
494 Get the current error state for the activity. |
|
495 @return The activity's current error state. @c KErrNone indicates there is no error. |
|
496 */ |
|
497 TInt Error() const |
|
498 { |
|
499 return iError; |
|
500 } |
|
501 |
|
502 /** |
|
503 Set the error state of the activity. |
|
504 |
|
505 @param aError error code to set |
|
506 */ |
|
507 void SetError(TInt aError) |
|
508 { |
|
509 if (iError == KErrNone || aError == KErrNone) |
|
510 { |
|
511 iError = aError; |
|
512 }; |
|
513 } |
|
514 |
|
515 /** |
|
516 Get the id of the node that the last request from this activity was sent to. |
|
517 @return Node id of the last node the activity has posted a request to |
|
518 */ |
|
519 const Messages::TNodeId PostedToId() const |
|
520 { |
|
521 return iPostedToId; |
|
522 } |
|
523 |
|
524 /** |
|
525 Get the id of the message that started this activity. |
|
526 @return Message id of message that kicked off this activity |
|
527 */ |
|
528 const Messages::TNodeSignal::TMessageId KickOffMessageId() const |
|
529 { |
|
530 return Messages::TNodeSignal::TMessageId(iActivitySig.iKickOffMessageId, iActivitySig.iKickOffMessageRealm); |
|
531 } |
|
532 |
|
533 /** |
|
534 Get the id of the node that started this activity. |
|
535 @return Node peer id of the node whose message first kicked off this activity |
|
536 */ |
|
537 const Messages::TNodePeerId& FirstOriginator() const |
|
538 { |
|
539 __ASSERT_DEBUG(iOriginators.Count(), User::Panic(KSpecAssert_ElemMeshMachActH, 1)); |
|
540 return iOriginators[0]; |
|
541 } |
|
542 |
|
543 /** |
|
544 In essence the same as FirstOriginator(). This should be used in preference in situations where the activity should |
|
545 be run in parallel, and therefore only ever have one originator. |
|
546 @return Node peer id of the node whose message first kicked off this activity |
|
547 */ |
|
548 const Messages::TNodePeerId& SoleOriginator() const |
|
549 { |
|
550 __ASSERT_DEBUG(iOriginators.Count() == 1, User::Panic(KSpecAssert_ElemMeshMachActH, 2)); |
|
551 return iOriginators[0]; |
|
552 } |
|
553 |
|
554 /** |
|
555 Post a request to a node. |
|
556 |
|
557 @param aRecepient Endpoint for the message |
|
558 @param aMessage Message to send |
|
559 @param aRecipientIdCritical If true, the postedTo id is set to the id of the recipient. If false, the postedTo id is set to null. |
|
560 @see PostedToId |
|
561 */ |
|
562 IMPORT_C void PostRequestTo(const Messages::RNodeInterface& aRecepient, const Messages::TSignalBase& aMessage, const TBool aRecipientIdCritical = ETrue); |
|
563 /** |
|
564 Post a request to a node. |
|
565 |
|
566 @param aRecepient Endpoint for the message |
|
567 @param aMessage Message to send |
|
568 @param aRecipientIdCritical If true, the postedTo id is set to the id of the recipient. If false, the postedTo id is set to null. |
|
569 @see PostedToId |
|
570 */ |
|
571 IMPORT_C void PostRequestTo(const Messages::TNodeId& aRecepient, const Messages::TSignalBase& aMessage, const TBool aRecipientIdCritical = ETrue); |
|
572 |
|
573 /** |
|
574 Manually set the postedTo id |
|
575 |
|
576 @param aNodeId Node id to set the postedTo id to |
|
577 */ |
|
578 IMPORT_C void SetPostedTo(const Messages::TNodeId& aNodeId); |
|
579 |
|
580 /** |
|
581 Clear the postedTo id |
|
582 */ |
|
583 IMPORT_C void ClearPostedTo(); |
|
584 |
|
585 #ifdef SYMBIAN_TRACE_ENABLE |
|
586 /** |
|
587 @return the human readable name of the activity |
|
588 */ |
|
589 const TText8* ActivityName() const |
|
590 { |
|
591 return (iActivitySig.iName)? iActivitySig.iName : _S8("Undefined"); |
|
592 } |
|
593 |
|
594 /** |
|
595 @return the human readable description of the current node activity entry |
|
596 */ |
|
597 const TText8* CurrentTripleName() const |
|
598 { |
|
599 return ACore::CurrentTripleName(); |
|
600 } |
|
601 #endif |
|
602 |
|
603 public: |
|
604 /** |
|
605 Cancels the activity. Only to be called by the meshmachine. |
|
606 @param aContext the context in which the activity is being executed |
|
607 @internalAll |
|
608 */ |
|
609 IMPORT_C virtual void Cancel(TNodeContextBase& aContext); |
|
610 |
|
611 /** |
|
612 Attempt to advance the activity one entry. Only to be called by the mesh machine |
|
613 @param aContext the context in which the activity is being executed |
|
614 @return Whether the activity advanced |
|
615 @internalAll |
|
616 */ |
|
617 IMPORT_C virtual TBool Next(TNodeContextBase& aContext); |
|
618 |
|
619 /** |
|
620 Find the originator matching the parameters |
|
621 @param aPeerToFind Matching criteria |
|
622 @return Index of the matching originator. KErrNotFound if not found. |
|
623 @internalAll |
|
624 */ |
|
625 IMPORT_C TInt FindOriginator(const Messages::RNodeInterface& aPeerToFind) const; |
|
626 |
|
627 /** |
|
628 Find the originator matching the parameters |
|
629 @param aPeerToFind Matching criteria |
|
630 @return Index of the matching originator. KErrNotFound if not found. |
|
631 @internalAll |
|
632 */ |
|
633 IMPORT_C TInt FindOriginator(const Messages::TRuntimeCtxId& aPeerToFind) const; |
|
634 |
|
635 /** |
|
636 Find the originator matching the parameters |
|
637 @param aOriginator xx |
|
638 @return Index of the matching originator. KErrNotFound if not found. |
|
639 |
|
640 @internalAll |
|
641 */ |
|
642 IMPORT_C TInt FindOriginator(const Messages::TNodePeerId& aOriginator) const; |
|
643 |
|
644 /** |
|
645 Post a message to an originator |
|
646 @param aOriginator originator to post the message to |
|
647 @param aMessage message to post |
|
648 @return Whether the posting succeeded |
|
649 @internalAll |
|
650 */ |
|
651 IMPORT_C TBool PostToOriginator(const Messages::TNodePeerId& aOriginator, const Messages::TSignalBase& aMessage) const; |
|
652 |
|
653 /** |
|
654 Post a message to all originators |
|
655 @param aMessageSig the message to post |
|
656 @param aFlagsToSet Flags to set on the peer as the message is being sent |
|
657 @param aFlagsToClear Flags to cleared on the peer as the message is being sent |
|
658 @return number of originators the message was posted to |
|
659 @internalAll |
|
660 */ |
|
661 IMPORT_C TInt PostToOriginators(const Messages::TSignalBase& aMessageSig, TUint32 aFlagsToSet = 0, TUint32 aFlagsToClear = 0); |
|
662 |
|
663 /** |
|
664 Calls cancel on current state. Sends TError to all originators and sets activity idle |
|
665 @param aContext the context in which the activity is being executed |
|
666 @param aIsNodeBeingDestroyed indicate to the activity as to whether the node is being destroyed |
|
667 @internalAll |
|
668 */ |
|
669 IMPORT_C void Abort(TNodeContextBase& aContext, TBool aIsNodeBeingDestroyed = EFalse); |
|
670 |
|
671 |
|
672 protected: |
|
673 /** |
|
674 Constructor for CNodeActivityBase |
|
675 @param aActivitySig Signature with which to create the activity |
|
676 @param aNode Node which will own the activity |
|
677 */ |
|
678 IMPORT_C explicit CNodeActivityBase(const TNodeActivity& aActivitySig, AMMNodeBase& aNode); |
|
679 /** |
|
680 Destructor. If the Activity is running in error mode, a message is sent to the originator. |
|
681 */ |
|
682 IMPORT_C virtual ~CNodeActivityBase(); |
|
683 |
|
684 /** |
|
685 Destroy the activity. |
|
686 |
|
687 Used primarily by preallocated activities to return extracted space |
|
688 */ |
|
689 virtual void Destroy() |
|
690 { |
|
691 delete this; |
|
692 }; |
|
693 |
|
694 /** |
|
695 |
|
696 @param aInterfaceId id of requested interface |
|
697 @return Interface control for accessing the extension interfaces of the activity |
|
698 @see TInterfaceControl |
|
699 */ |
|
700 IMPORT_C virtual NetInterfaces::TInterfaceControl* DoFetchInterfaceControlL(TInt aInterfaceId); |
|
701 |
|
702 /** |
|
703 Signal the activity that an event has happened in the mesh machine. Used for waking up sleeping activities |
|
704 which use mutexes. |
|
705 |
|
706 @param # The context in which the activity is being executed |
|
707 @return ETrue if the activity was awoken |
|
708 @see AActivitySemaphore |
|
709 */ |
|
710 virtual TBool Signal(TNodeContextBase& /*aContext*/) { return EFalse; }; |
|
711 |
|
712 protected: |
|
713 /** |
|
714 Test whether a activity can start given the current context. If it can, the first transition will be executed. |
|
715 Note that this is a static method, and as such the activity hasn't been instanciated when this is called |
|
716 |
|
717 @param aContext the context in which the activity may be executed |
|
718 @param aActivitySig the activity which we are testing for the accept condition |
|
719 @param aTransitionTag the condition which must be matched by the first entry for the activity to be accepted. Set to KExecuteAlways to skip this check |
|
720 |
|
721 @return the first entry triple for the activity if it's accepted. NULL otherwise |
|
722 */ |
|
723 static const NetStateMachine::TStateTriple* Accept(TNodeContextBase& aContext, const TNodeActivity& aActivitySig, TInt aTransitionTag); |
|
724 |
|
725 /** |
|
726 Start a new activity. The first transition should have been run within the @c Accept() method before this is called. |
|
727 |
|
728 @param aContext The context to start the activity in |
|
729 @param aOriginator The peer that requires this activity to start |
|
730 @param aFirst First entry triple in the activity, as returned by @c Accept() |
|
731 */ |
|
732 IMPORT_C virtual void StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const NetStateMachine::TStateTriple& aFirst); |
|
733 |
|
734 protected: |
|
735 /** |
|
736 Append self to the node's list of running activities. |
|
737 |
|
738 Should only be accessed from @c Activity::NewL. Generally activities can choose to be inserted or appended |
|
739 (if they do not choose they are appended by default). When inserting, extreme caution must be taken, as |
|
740 this behavior is reserved for destroying activities. |
|
741 */ |
|
742 IMPORT_C void AppendActivityL(); |
|
743 |
|
744 /** |
|
745 Append self to the node's list of running activities. This should only be called if you are certain that |
|
746 the activity list has space for the append. |
|
747 */ |
|
748 IMPORT_C void AppendPreallocatedActivity(); |
|
749 |
|
750 /** |
|
751 Insert an activity at the start of the node's list of running activities. |
|
752 */ |
|
753 IMPORT_C void InsertPreallocatedDestroyActivity(); |
|
754 |
|
755 /** |
|
756 Borrow some preallocated memory from the node. This preallocated memory is used for activities that |
|
757 absolutely cannot fail in any scenario, such as for Destroying the node. For this reason, when the |
|
758 node is created, some memory is allocated so that a destroying activity can't even fail in an out |
|
759 of memory situation. |
|
760 |
|
761 This method is static as the memory must be borrowed before the activity object is constructed. |
|
762 |
|
763 The memory is returned using @c ReturnPreallocatedSpace(). |
|
764 |
|
765 @param aNode The node that owns the preallocated space. This must be the node that the activity runs on. |
|
766 @param aSize Size of buffer to allocate. |
|
767 |
|
768 @return A pointer to the allocated block of memory |
|
769 */ |
|
770 IMPORT_C static TAny* BorrowPreallocatedSpace(AMMNodeBase& aNode, TUint aSize); |
|
771 |
|
772 /** |
|
773 Return preallocated space to the node. The node does not have to be passed in as a parameter as it will |
|
774 already be a member of the activity. |
|
775 |
|
776 @param aSpace Memory buffer to return. |
|
777 */ |
|
778 IMPORT_C void ReturnPreallocatedSpace(TAny* aSpace); |
|
779 |
|
780 /** |
|
781 Test whether aContext carries a message that is to be expected by 'this' in its current state. |
|
782 The method is effectivelly a filter that hides the messages flowing throught the node, but not |
|
783 intended for 'this'. The method will check: |
|
784 - if aContext carries a message from PostedToId (if set) then the message should be presented to 'this'. |
|
785 - if aContext carries a message from one of the originators then the message should be presented to 'this'. |
|
786 @return ETrue if the sender of the current message matches PostedToId if it is set. |
|
787 */ |
|
788 IMPORT_C TBool MatchSender(const TNodeContextBase& aContext) const; |
|
789 |
|
790 protected: |
|
791 /** |
|
792 The node the activity is running on |
|
793 */ |
|
794 AMMNodeBase& iNode; |
|
795 |
|
796 /** |
|
797 All the nodes that have started the same activity |
|
798 */ |
|
799 RArray<Messages::XNodePeerId> iOriginators; |
|
800 |
|
801 private: //Shouldn't be accessed directly |
|
802 TInt iError; //Risk of failure is a generic property of an activity. |
|
803 //Activities may choose to use external error handling activities, |
|
804 //or may choose to handle errors locally. In the latter case, |
|
805 //the activity may want to know it's running an error mode |
|
806 //(by setting this member). |
|
807 //iError must be cleared before the activity goes out of scope |
|
808 //to indicate the error has been handled. |
|
809 |
|
810 const TNodeActivity& iActivitySig; |
|
811 |
|
812 // Last node a message was sent to |
|
813 Messages::TNodeId iPostedToId; |
|
814 }; |
|
815 |
|
816 |
|
817 /** |
|
818 Activity type that generates a unique activity id every time it is instantiated. |
|
819 The id is generated from the @c <TNodeActivityId::EActivityParallelRangeMin,TCFNodeActivityId::EActivityParallelRangeMax> |
|
820 range. The id should never be found in a static activity map. |
|
821 A new instance id is created rather than adding a new originator to the existing activity. |
|
822 */ |
|
823 class CNodeParallelActivityBase : public CNodeActivityBase |
|
824 |
|
825 { |
|
826 public: |
|
827 /** |
|
828 Create a new activity. This should never be called by user code. |
|
829 |
|
830 @param aActivitySig Context information about how the activity is to be started |
|
831 @param aNode The node to which this activity will belong. |
|
832 @return A pointer to the new activity. Ownership is transfered. |
|
833 */ |
|
834 IMPORT_C static CNodeActivityBase* NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode ); |
|
835 |
|
836 /** |
|
837 Get the activity id |
|
838 @return The activity id of the activity |
|
839 */ |
|
840 IMPORT_C virtual TUint16 ActivityId() const; |
|
841 |
|
842 protected: |
|
843 /** |
|
844 For use by custom activity NewLs to generate the unique part of the activity id. |
|
845 @param aActivitySig Context information about how the activity is to be started |
|
846 @param aNode The node to which this activity will belong. |
|
847 @return Generated unique component of activity id |
|
848 */ |
|
849 IMPORT_C static TUint GetNextActivityCountL( const TNodeActivity& aActivitySig, const AMMNodeBase& aNode ); |
|
850 |
|
851 /** |
|
852 Constructor for CNodeParallelActivityBase |
|
853 @param aActivitySig Context information about how the activity is to be started |
|
854 @param aNode The node to which this activity will belong. |
|
855 @param aNextActivityCount The unique part of the activity id |
|
856 */ |
|
857 IMPORT_C CNodeParallelActivityBase( const TNodeActivity& aActivitySig, AMMNodeBase& aNode, TUint aNextActivityCount ); |
|
858 |
|
859 protected: |
|
860 /** |
|
861 The activity id. The id format is [8 bit unique id|8 bit activity sig]. |
|
862 */ |
|
863 TUint16 iActivityId; |
|
864 }; |
|
865 |
|
866 /** |
|
867 Base class for parallel activities which store their kickoff message. |
|
868 |
|
869 @see CNodeParallelActivityBase |
|
870 */ |
|
871 class CNodeParallelMessageStoreActivityBase : public CNodeParallelActivityBase |
|
872 { |
|
873 public: |
|
874 IMPORT_C static CNodeActivityBase* NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ); |
|
875 IMPORT_C ~CNodeParallelMessageStoreActivityBase(); |
|
876 |
|
877 /** |
|
878 @return Kick off message for this activity |
|
879 */ |
|
880 IMPORT_C Messages::TSignalBase& Message(); |
|
881 |
|
882 protected: |
|
883 IMPORT_C virtual void StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const NetStateMachine::TStateTriple& aFirst); |
|
884 void SaveMessageL(Messages::TSignalBase& aMessage); |
|
885 |
|
886 IMPORT_C CNodeParallelMessageStoreActivityBase( const MeshMachine::TNodeActivity& aActivitySig, |
|
887 MeshMachine::AMMNodeBase& aNode, TUint aNextActivityCount ); |
|
888 |
|
889 private: |
|
890 Messages::TSignalBase* iMsg; |
|
891 TBuf8<__Align8(Messages::TSignalBase::KMaxInlineMessageSize + Messages::TSignalBase::KMaxUnstoredOverhead)> iMsgBuf; |
|
892 }; |
|
893 |
|
894 /** |
|
895 |
|
896 If an activity has a transition or fork that is blocked by a mutex, the context must be stored so |
|
897 that when the transition or fork is unblocked it would be able to continue with the context that |
|
898 it had before it was blocked. If this aggregate wasn't used in the previous scenario, the context |
|
899 of the event that triggered the unblocking would be used, and this may have the wrong message, or |
|
900 event originator set. |
|
901 |
|
902 Error recovery is another scenario this class is useful in. |
|
903 */ |
|
904 class AContextStore |
|
905 { |
|
906 public: |
|
907 /** |
|
908 Interface id |
|
909 */ |
|
910 static const TInt KInterfaceId = 0x102864DC; |
|
911 |
|
912 protected: |
|
913 /** |
|
914 Constructor for AContextStore |
|
915 */ |
|
916 explicit AContextStore() |
|
917 { |
|
918 } |
|
919 /** |
|
920 Destructor for AContextStore |
|
921 */ |
|
922 ~AContextStore() |
|
923 { |
|
924 iContextDesc.Close(); |
|
925 } |
|
926 |
|
927 public: |
|
928 /** |
|
929 Used for error recovery. If the context is stored, loads the stored context and reruns the last transition that was run. |
|
930 |
|
931 @param aActivity The activity to retry |
|
932 @param aContext The context within which the retrying is taking place. NOTE: This is not the stored context |
|
933 |
|
934 @see StoreContext |
|
935 @see LoadContext |
|
936 */ |
|
937 IMPORT_C void Retry(CNodeActivityBase& aActivity, TNodeContextBase& aContext); |
|
938 |
|
939 /** |
|
940 Store context in buffer. Designed to be called from a transition to store the transitions context for error recovery or |
|
941 to wait on a mutex. |
|
942 |
|
943 @param aContext The context to store |
|
944 @return Error code. @c KErrNone if storage is successful. |
|
945 */ |
|
946 IMPORT_C TInt StoreContext(const TNodeContextBase& aContext); |
|
947 |
|
948 /** |
|
949 Check of the context is stored. |
|
950 @return @c ETrue if a context is stored. @c EFalse otherwise. |
|
951 */ |
|
952 IMPORT_C TBool IsStored() const; |
|
953 |
|
954 /** |
|
955 Get the id of the message which requested @c Retry() |
|
956 @return Message Id of message which kicked off the @c ::Retry |
|
957 |
|
958 @see AContextStore::Retry |
|
959 */ |
|
960 IMPORT_C const Messages::TNodeSignal::TMessageId& RetryingForMessageId() const; //Needs to be moved to error-recoverable activity class |
|
961 |
|
962 protected: |
|
963 /** |
|
964 Load a stored context. Once the stored context has been loaded the status of @c iContextDesc is undefined and load shouldn't |
|
965 be called again until something has been stored. |
|
966 |
|
967 The pointer returned uses memory allocated in the @c aCtxBuff that is passed in, and as such, does not need to be freed. However @c aCtxBuff and @c aMsgBuff |
|
968 must be cleaned up after use. |
|
969 |
|
970 @param aNode The node for the context |
|
971 @param aNodeActivity The activity for the context. |
|
972 @param aCtxBuff A memory buffer in which the context will be created. |
|
973 @param aMsgBuff A memory buffer in which the message will be created. |
|
974 @param aDummy Will become the recipient node id in the context. |
|
975 |
|
976 @return Pointer to loaded context |
|
977 */ |
|
978 IMPORT_C TNodeContextBase* LoadContext(AMMNodeBase& aNode, CNodeActivityBase* aNodeActivity, TDes8& aCtxBuff, TDes8& aMsgBuff, const Messages::TNodeId& aDummy); |
|
979 |
|
980 protected: |
|
981 /** |
|
982 Buffer to store the context. |
|
983 */ |
|
984 RBuf8 iContextDesc; |
|
985 /** |
|
986 Message id of the message which kicked off the retry attempt |
|
987 */ |
|
988 Messages::TNodeSignal::TMessageId iRetryingForMessageId; |
|
989 }; |
|
990 |
|
991 /** |
|
992 Aggregate class for activities which wish to use mutexes. |
|
993 |
|
994 After a serialised state or transition has been unblocked, signalled and invoked, AActivitySemaphore |
|
995 clears all of the synchronisation related information (e.g stored context), assuming that the job has |
|
996 been done. Sometimes however the serialised state, upon more careful inspection of the environment |
|
997 (context), may decide that it still does not want to be executed and it wishes to sleep again. |
|
998 |
|
999 In such case it would call Wait() and return @c EIgnore from its @c TransitionTag(). The same applies to a |
|
1000 serialised transition. It may want to call Wait() instead of, for example sending a request message. |
|
1001 |
|
1002 After calling Wait() the serialised state will be woken up when the policy matches, which allows the serialised state |
|
1003 to finish its job. |
|
1004 */ |
|
1005 class AActivitySemaphore : public AContextStore |
|
1006 { |
|
1007 public: |
|
1008 /** |
|
1009 Interface id |
|
1010 */ |
|
1011 static const TInt KInterfaceId = 10015; //Normally a UID - 10015 for compatibility reasons |
|
1012 |
|
1013 public: |
|
1014 /** |
|
1015 Park a state. |
|
1016 |
|
1017 @param aContext The context which the state is to run in. This will be stored |
|
1018 |
|
1019 @return @c KErrNone if successful. System wide error code otherwise |
|
1020 */ |
|
1021 IMPORT_C static TInt ParkState(const TNodeContextBase& aContext); |
|
1022 |
|
1023 /** |
|
1024 Unpark a state. |
|
1025 |
|
1026 @param aContext The context which the state is to run in. |
|
1027 |
|
1028 @return @c KErrNone if successful. System wide error code otherwise |
|
1029 */ |
|
1030 IMPORT_C static TInt UnparkState(const TNodeContextBase& aContext); |
|
1031 |
|
1032 /** |
|
1033 Park a transition |
|
1034 |
|
1035 @param aContext The context which the transition is to run in. |
|
1036 */ |
|
1037 IMPORT_C static void ParkTransitionL(const TNodeContextBase& aContext); |
|
1038 |
|
1039 /** |
|
1040 Signals to the activity that an event has occurred. Used for waking up sleeping activities |
|
1041 which use mutexes. The activity is expected to check if the mutex has now cleared. |
|
1042 |
|
1043 @param aContext Current context in the state machine. |
|
1044 |
|
1045 @return @c ETrue if the state or transition has been unparked |
|
1046 */ |
|
1047 IMPORT_C TBool Signal(TNodeContextBase& aContext); |
|
1048 |
|
1049 /** |
|
1050 Tell the activity to wait. The activity will wait until Signal() is called. |
|
1051 */ |
|
1052 IMPORT_C void Wait(); |
|
1053 |
|
1054 /** |
|
1055 Check if the activity is waiting |
|
1056 @return ETrue if the activity is currently waiting |
|
1057 */ |
|
1058 TBool IsWaiting() const |
|
1059 { |
|
1060 __ASSERT_DEBUG(!(iFlags&KIsWaiting) || IsStored(), User::Panic(KSpecAssert_ElemMeshMachActH, 3)); |
|
1061 |
|
1062 return iFlags&KIsWaiting; |
|
1063 } |
|
1064 |
|
1065 protected: |
|
1066 /** |
|
1067 Constructor for AActivitySemaphore |
|
1068 */ |
|
1069 explicit AActivitySemaphore() |
|
1070 : iFlags(0) |
|
1071 { |
|
1072 } |
|
1073 /** |
|
1074 Destructor for AActivitySemaphore |
|
1075 */ |
|
1076 ~AActivitySemaphore() |
|
1077 { |
|
1078 } |
|
1079 |
|
1080 protected: |
|
1081 /** |
|
1082 Set the @c isWaiting flag |
|
1083 */ |
|
1084 inline void SetIsWaiting() { iFlags|=KIsWaiting; }; |
|
1085 /** |
|
1086 Clear the @c isWaiting flag |
|
1087 */ |
|
1088 inline void ClearIsWaiting() { iFlags&=~KIsWaiting; }; |
|
1089 |
|
1090 /** |
|
1091 Check if the WillWait flag is set. The WillWait flag indicates whether the activity will be in a waiting state at the end of the signal function. |
|
1092 This is distinct from "is waiting" which indicates whether the activity was waiting on entry to the Signal() |
|
1093 function. |
|
1094 |
|
1095 @return ETrue if the WillWait flag is set |
|
1096 */ |
|
1097 inline TBool WillWait() const { return (iFlags&KWillWait)==KWillWait; }; |
|
1098 /** |
|
1099 Set the willWait flag |
|
1100 */ |
|
1101 inline void SetWillWait() { iFlags|=KWillWait; }; |
|
1102 /** |
|
1103 Clear the willWait flag |
|
1104 */ |
|
1105 inline void ClearWillWait() { iFlags&=~KWillWait; }; |
|
1106 |
|
1107 private: |
|
1108 //Is waiting for mutex? == not idle yet, even if last triple |
|
1109 //iIsWaiting prevents Idle condition following the last |
|
1110 //transition (in case the transition has parked the activity |
|
1111 //and wants to be reexecuted). When reexecuting, the activity |
|
1112 //mustn't be idle (iIsWaiting has to be true), on the |
|
1113 //other hand the transition may to park the activity again |
|
1114 //We need to distinguish the entry value of iIsWaiting from |
|
1115 //the exit value of iIsWaiting, we hance need this aditional |
|
1116 //flag. |
|
1117 |
|
1118 inline TBool IsTransition() const { return (iFlags&KIsTransition)==KIsTransition; }; |
|
1119 inline void SetIsTransition() { iFlags|=KIsTransition; }; |
|
1120 inline void ClearIsTransition() { iFlags&=~KIsTransition; }; |
|
1121 |
|
1122 enum { KIsWaiting = 0x1, KWillWait = 0x2, KIsTransition = 0x4 }; |
|
1123 |
|
1124 TUint8 iFlags; |
|
1125 }; |
|
1126 |
|
1127 /** |
|
1128 Activity class base for activities which wish to use synchronisation or retries. |
|
1129 */ |
|
1130 class CNodeRetryActivity : public CNodeActivityBase, public AActivitySemaphore, |
|
1131 public ITFHIERARCHY_2(CNodeRetryActivity, AContextStore, AActivitySemaphore) |
|
1132 { |
|
1133 public: |
|
1134 /** |
|
1135 Defines a helper list of interfaces. |
|
1136 */ |
|
1137 typedef ITFHIERARCHY_2(CNodeRetryActivity, AContextStore, AActivitySemaphore) TIfStaticFetcherNearestInHierarchy; |
|
1138 |
|
1139 public: |
|
1140 /** |
|
1141 Create a new activity. This should never be called by user code. |
|
1142 |
|
1143 @param aActivitySig Context information about how the activity is to be started |
|
1144 @param aNode The node to which this activity will belong. |
|
1145 @return A pointer to the new object. Ownership is transfered. |
|
1146 */ |
|
1147 IMPORT_C static CNodeActivityBase* NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode ); |
|
1148 |
|
1149 /** |
|
1150 Fetch the context store interface |
|
1151 @param aInterface pointer into which a pointer to the interface will be placed. |
|
1152 */ |
|
1153 IMPORT_C void ReturnInterfacePtrL(AContextStore*& aInterface); |
|
1154 |
|
1155 /** |
|
1156 Fetch the activity semaphore interface |
|
1157 @param aInterface On return, contains a pointer to the interface. |
|
1158 */ |
|
1159 IMPORT_C void ReturnInterfacePtrL(AActivitySemaphore*& aInterface); |
|
1160 |
|
1161 /** |
|
1162 Check if the activity has stopped running |
|
1163 @return @c ETrue if the activity is still running, otherwise @c EFalse. |
|
1164 */ |
|
1165 IMPORT_C virtual TBool IsIdle() const; |
|
1166 |
|
1167 /** |
|
1168 Put the activity into the idle state. This stops the activity running and notifies the mesh machine that |
|
1169 it is ok to delete this activity. |
|
1170 */ |
|
1171 IMPORT_C virtual void SetIdle(); |
|
1172 |
|
1173 protected: |
|
1174 /** |
|
1175 Signal the activity that an event has occurred and that it is worthwhile checking |
|
1176 to see if the mutex has now cleared. |
|
1177 |
|
1178 @param aContext Current context in the state machine. |
|
1179 |
|
1180 @return @c ETrue if state or transition has been unparked |
|
1181 */ |
|
1182 IMPORT_C virtual TBool Signal(TNodeContextBase& aContext); |
|
1183 |
|
1184 /** |
|
1185 Constructor for CNodeRetryActivity |
|
1186 @param aActivitySig Context information about how the activity is to be started |
|
1187 @param aNode The node to which this activity will belong. |
|
1188 */ |
|
1189 IMPORT_C CNodeRetryActivity( const TNodeActivity& aActivitySig, AMMNodeBase& aNode ); |
|
1190 }; |
|
1191 |
|
1192 /** |
|
1193 Base class for activities that run in parallel and can be synchronised or retried. |
|
1194 */ |
|
1195 class CNodeRetryParallelActivity : public CNodeParallelActivityBase, public AActivitySemaphore, |
|
1196 public ITFHIERARCHY_2(CNodeRetryParallelActivity, AContextStore, AActivitySemaphore) |
|
1197 { |
|
1198 public: |
|
1199 /** |
|
1200 Defines a helper list of interfaces. |
|
1201 */ |
|
1202 typedef ITFHIERARCHY_2(CNodeRetryParallelActivity, AContextStore, AActivitySemaphore) TIfStaticFetcherNearestInHierarchy; |
|
1203 |
|
1204 public: |
|
1205 /** |
|
1206 Create a new activity. This should never be called by user code. |
|
1207 |
|
1208 @param aActivitySig Context information about how the activity is to be started |
|
1209 @param aNode The node to which this activity will belong. |
|
1210 @return A pointer to the new object. Ownership is transfered. |
|
1211 */ |
|
1212 IMPORT_C static CNodeActivityBase* NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode ); |
|
1213 |
|
1214 /** |
|
1215 Fetch the context store interface |
|
1216 @param aInterface On return, contains a pointer to the store interface |
|
1217 */ |
|
1218 IMPORT_C void ReturnInterfacePtrL(AContextStore*& aInterface); |
|
1219 |
|
1220 /** |
|
1221 Fetch the activity semaphore interface |
|
1222 @param aInterface On return, contains a pointer to the semaphore interface |
|
1223 */ |
|
1224 IMPORT_C void ReturnInterfacePtrL(AActivitySemaphore*& aInterface); |
|
1225 |
|
1226 /** |
|
1227 Check if the activity has stopped |
|
1228 @return @c ETrue if the activity is still running, otherwise @c EFalse |
|
1229 */ |
|
1230 IMPORT_C virtual TBool IsIdle() const; |
|
1231 |
|
1232 /** |
|
1233 Put the activity into the idle state. This stops the activity running and notifies the mesh machine that |
|
1234 it is ok to delete this activity. |
|
1235 */ |
|
1236 IMPORT_C virtual void SetIdle(); |
|
1237 |
|
1238 protected: |
|
1239 /** |
|
1240 Signal to the activity that an event has occurred and that it is worthwhile checking |
|
1241 to see if the mutex has now cleared. |
|
1242 |
|
1243 @param aContext Current context in the state machine. |
|
1244 |
|
1245 @return @c ETrue if state or transition has been unparked |
|
1246 */ |
|
1247 IMPORT_C virtual TBool Signal(TNodeContextBase& aContext); |
|
1248 |
|
1249 /** |
|
1250 Constructor for CNodeRetryParallelActivity |
|
1251 |
|
1252 @param aActivitySig Context information about how the activity is to be started |
|
1253 @param aNode The node to which this activity will belong. |
|
1254 @param aActivitiesCount The unique part of the activity id |
|
1255 */ |
|
1256 IMPORT_C CNodeRetryParallelActivity( const TNodeActivity& aActivitySig, AMMNodeBase& aNode, TUint aActivitiesCount ); |
|
1257 }; |
|
1258 |
|
1259 /** |
|
1260 Aggregate originator array template for activities that use preallocated space. |
|
1261 This object has a fixed size array to hold the originators which will be allocated from the preallocated space |
|
1262 when the node activity object is created. |
|
1263 */ |
|
1264 template <TInt ORIGINATORSCOUNT> |
|
1265 class APreallocatedOriginators |
|
1266 { |
|
1267 protected: |
|
1268 /** |
|
1269 Initialise the array and ensure it is empty as it should be on creation. |
|
1270 Generally, iOriginators from the activity will be passed into this as a reference. A new |
|
1271 RArray will then be created using the preallocated space. |
|
1272 |
|
1273 @param aOriginators Array of originators for which to preallocate space |
|
1274 */ |
|
1275 explicit APreallocatedOriginators(RArray<Messages::XNodePeerId>& aOriginators) |
|
1276 : iOriginatorsRef(aOriginators) |
|
1277 { |
|
1278 iOriginatorsRef = RArray<Messages::XNodePeerId>(sizeof(Messages::XNodePeerId), (Messages::XNodePeerId*)iOriginatorBuf, ORIGINATORSCOUNT); |
|
1279 for (TInt i = iOriginatorsRef.Count() - 1; i >= 0; --i) |
|
1280 { |
|
1281 iOriginatorsRef.Remove(i); |
|
1282 } |
|
1283 } |
|
1284 /** |
|
1285 Destructor for APreallocatedOriginators. |
|
1286 */ |
|
1287 ~APreallocatedOriginators() |
|
1288 { |
|
1289 iOriginatorsRef = RArray<Messages::XNodePeerId>(); |
|
1290 } |
|
1291 |
|
1292 private: |
|
1293 //The originator's list |
|
1294 RArray<Messages::XNodePeerId>& iOriginatorsRef; |
|
1295 //Preallocated space in the originator's list |
|
1296 TUint8 iOriginatorBuf[__Align8(sizeof(Messages::XNodePeerId) * ORIGINATORSCOUNT)]; |
|
1297 }; |
|
1298 |
|
1299 /** |
|
1300 Base for preallocated node activity class |
|
1301 */ |
|
1302 template <TInt ORIGINATORSCOUNT> |
|
1303 class CPreallocatedNodeActivityBase : public MeshMachine::CNodeActivityBase, |
|
1304 protected MeshMachine::APreallocatedOriginators<ORIGINATORSCOUNT> |
|
1305 /** |
|
1306 @internalTechnology |
|
1307 */ |
|
1308 { |
|
1309 public: |
|
1310 /** |
|
1311 Create a new activity. This should never be called by user code. |
|
1312 |
|
1313 @param aActivitySig Context information about how the activity is to be started |
|
1314 @param aNode The node to which this activity will belong. |
|
1315 */ |
|
1316 static MeshMachine::CNodeActivityBase* New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1317 { |
|
1318 TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CPreallocatedNodeActivityBase)); |
|
1319 CPreallocatedNodeActivityBase* self = new (space) CPreallocatedNodeActivityBase(aActivitySig, aNode); |
|
1320 self->AppendPreallocatedActivity(); |
|
1321 return self; |
|
1322 } |
|
1323 |
|
1324 protected: |
|
1325 |
|
1326 |
|
1327 CPreallocatedNodeActivityBase(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1328 : CNodeActivityBase(aActivitySig, aNode), |
|
1329 APreallocatedOriginators<ORIGINATORSCOUNT>(iOriginators) |
|
1330 { |
|
1331 } |
|
1332 |
|
1333 /** |
|
1334 Destroy the activity. Return the preallocated space and call the destructor directly. i.e. not though delete |
|
1335 as delete would try and release the memory again |
|
1336 */ |
|
1337 virtual void Destroy() |
|
1338 { |
|
1339 ReturnPreallocatedSpace(this); |
|
1340 this->~CPreallocatedNodeActivityBase(); //Run the destructor |
|
1341 } |
|
1342 private: |
|
1343 /** |
|
1344 Private NewL with no implementation to hide the CNodeActivityBase::NewL |
|
1345 Creation of preallocated activities doesn't fail and hence a non-leaving ::New should be used instead |
|
1346 */ |
|
1347 static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); |
|
1348 }; |
|
1349 |
|
1350 //-========================================================= |
|
1351 // |
|
1352 // CPreallocatedNodeActivityBase |
|
1353 // |
|
1354 //-========================================================= |
|
1355 template <TInt ORIGINATORSCOUNT> |
|
1356 class CPreallocatedNodeRetryActivity : public MeshMachine::CNodeRetryActivity, |
|
1357 protected MeshMachine::APreallocatedOriginators<ORIGINATORSCOUNT> |
|
1358 /** |
|
1359 @internalTechnology |
|
1360 */ |
|
1361 { |
|
1362 public: |
|
1363 static MeshMachine::CNodeActivityBase* New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1364 { |
|
1365 TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CPreallocatedNodeRetryActivity)); |
|
1366 CPreallocatedNodeRetryActivity* self = new (space) CPreallocatedNodeRetryActivity(aActivitySig, aNode); |
|
1367 self->AppendPreallocatedActivity(); |
|
1368 return self; |
|
1369 } |
|
1370 |
|
1371 protected: |
|
1372 CPreallocatedNodeRetryActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1373 : CNodeRetryActivity(aActivitySig, aNode), |
|
1374 APreallocatedOriginators<ORIGINATORSCOUNT>(iOriginators) |
|
1375 { |
|
1376 } |
|
1377 |
|
1378 virtual void Destroy() |
|
1379 { |
|
1380 ReturnPreallocatedSpace(this); |
|
1381 this->~CPreallocatedNodeRetryActivity(); //Run the destructor |
|
1382 } |
|
1383 private: |
|
1384 /* |
|
1385 Private NewL with no implementation to hide the CNodeActivityBase::NewL |
|
1386 Creation of preallocated activities doesn't fail and hence a non-leaving ::New should be used instead*/ |
|
1387 static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); |
|
1388 }; |
|
1389 |
|
1390 } //namespace MeshMachine |
|
1391 |
|
1392 #endif //SYMBIAN_MM_ACTIVITIES_H |
|
1393 |