|
1 // Copyright (c) 2006-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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @publishedPartner |
|
19 @released |
|
20 */ |
|
21 |
|
22 #ifndef SYMBIAN_NM_INTERFACES_H |
|
23 #define SYMBIAN_NM_INTERFACES_H |
|
24 |
|
25 //#include <elements/nm_signals.h> |
|
26 #include <elements/nm_address.h> |
|
27 #include <elements/nm_log.h> |
|
28 |
|
29 |
|
30 #ifdef _DEBUG |
|
31 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
32 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
33 _LIT(KSpecAssert_ElemNodeMessIntH, "ElemNodeMessIntH"); |
|
34 #endif |
|
35 |
|
36 namespace Messages |
|
37 { |
|
38 |
|
39 class MTransportSender; |
|
40 class ANode; |
|
41 class TSignalBase; |
|
42 |
|
43 |
|
44 class TClientType |
|
45 /* |
|
46 TClientType defines a technology agnostic collection of enums for types and |
|
47 flags describing various traits of peers. It is also a placeholder for these |
|
48 values. When implementing a relation with a peer, TClientType (or its technology |
|
49 specific override) can be used to collect informations about the peers. |
|
50 @see RNodeInterface |
|
51 */ |
|
52 { |
|
53 public: |
|
54 enum TType |
|
55 { |
|
56 //-============================================= |
|
57 // |
|
58 // 1. Types 32bits (a client can only have one type) |
|
59 // |
|
60 //-============================================= |
|
61 EAll = 0xFFFFFFFF, |
|
62 EUnknown = 0x00000000, |
|
63 ERegistrar = 0x00000001, //Useful general purpose role. |
|
64 //Used to represent simple non-standard or one-off or transient |
|
65 //roles which now do not need to be specially defined for these |
|
66 //simple and/or rare relationships. |
|
67 EWorker = 0x00000002, //Useful general purpose role. |
|
68 |
|
69 /** |
|
70 @internalTechnology |
|
71 Reserved types that can change at any time and must NOT be used under any circumstances. |
|
72 Please take care when defining derived client types (do not reference ELastReservedType). |
|
73 */ |
|
74 ELastReservedType_InternalTechnology_CanBeReusedAtAnyTime_DoNotUseInCode = 0x00000080, |
|
75 }; |
|
76 |
|
77 enum TFlags |
|
78 { |
|
79 //-============================================= |
|
80 // |
|
81 // 2. Flags 32bits (a client can have many flags) |
|
82 // |
|
83 //-============================================= |
|
84 ELeaving = 0x00000001, //Client has been sent the final goodbye message (e.g TClientLeavingRequest) |
|
85 //and we are awaiting the channel clear confirmation (e.g. TLeaveComplete). |
|
86 //No further communication with this client is safe as it assumes we discard |
|
87 //any references to it. For example it could destruct itself etc. |
|
88 EAdministrative = 0x00000002, //These clients perform some administrative tasks on our node. |
|
89 |
|
90 /** |
|
91 @internalTechnology |
|
92 Reserved flags that can change at any time and must NOT be used under any circumstances. |
|
93 Please take care when defining derived client flags (do not reference ELastReservedFlag). |
|
94 */ |
|
95 ELastReservedFlag_InternalTechnology_CanBeReusedAtAnyTime_DoNotUseInCode = 0x00000080 |
|
96 }; |
|
97 |
|
98 public: |
|
99 IMPORT_C static const TClientType& NullType(); |
|
100 |
|
101 TClientType() |
|
102 : iClientType(EUnknown), |
|
103 iClientFlags(0) |
|
104 { |
|
105 } |
|
106 |
|
107 TClientType(TUint aClientType, TUint aClientFlags = 0) |
|
108 : iClientType(aClientType), |
|
109 iClientFlags(aClientFlags) |
|
110 { |
|
111 } |
|
112 |
|
113 TClientType(const TClientType& aClientType) |
|
114 : iClientType(aClientType.iClientType), |
|
115 iClientFlags(aClientType.iClientFlags) |
|
116 { |
|
117 } |
|
118 |
|
119 TBool IsNull() const |
|
120 { |
|
121 return iClientType == 0 && iClientFlags == 0; |
|
122 } |
|
123 |
|
124 TUint32 Type() const |
|
125 { |
|
126 return iClientType; |
|
127 } |
|
128 |
|
129 TUint32 Flags() const |
|
130 { |
|
131 return iClientFlags; |
|
132 } |
|
133 |
|
134 TUint32 SetFlags(TUint32 aFlags) |
|
135 { |
|
136 return iClientFlags |= aFlags; |
|
137 } |
|
138 |
|
139 TUint32 ClearFlags(TUint32 aFlags) |
|
140 { |
|
141 return iClientFlags &= ~aFlags; |
|
142 } |
|
143 |
|
144 protected: |
|
145 TUint32 iClientType; |
|
146 TUint32 iClientFlags; |
|
147 }; |
|
148 |
|
149 //None of the specified |
|
150 struct TNoMatchPolicy |
|
151 { |
|
152 inline static TBool Match(TUint32 aVal, TUint32 aMatch) |
|
153 { |
|
154 return (aVal & aMatch) == 0; |
|
155 } |
|
156 }; |
|
157 |
|
158 //Any of the specified, can be more, can be less |
|
159 struct TAnyMatchPolicy |
|
160 { |
|
161 inline static TBool Match(TUint32 aVal, TUint32 aMatch) |
|
162 { |
|
163 return (aVal & aMatch) != 0; |
|
164 } |
|
165 }; |
|
166 |
|
167 //Any of the specified, both can be null, can be more, can be less |
|
168 struct TExactOrAnyMatchPolicy |
|
169 { |
|
170 inline static TBool Match(TUint32 aVal, TUint32 aMatch) |
|
171 { |
|
172 return (aVal == aMatch) || (aVal & aMatch) != 0; |
|
173 } |
|
174 }; |
|
175 |
|
176 //All of the specified, can't be more, can be less |
|
177 struct TSubSetMatchPolicy |
|
178 { |
|
179 inline static TBool Match(TUint32 aVal, TUint32 aMatch) |
|
180 { |
|
181 return (aVal & aMatch) == aVal; |
|
182 } |
|
183 }; |
|
184 |
|
185 //Any of the specified, can be more, can't be less |
|
186 struct TSuperSetMatchPolicy |
|
187 { |
|
188 inline static TBool Match(TUint32 aVal, TUint32 aMatch) |
|
189 { |
|
190 return (aVal & aMatch) == aMatch; |
|
191 } |
|
192 }; |
|
193 |
|
194 //All of the specified, can't be less, can't be more |
|
195 struct TExactMatchPolicy |
|
196 { |
|
197 inline static TBool Match(TUint32 aVal, TUint32 aMatch) |
|
198 { |
|
199 return aVal == aMatch; |
|
200 } |
|
201 }; |
|
202 |
|
203 template <typename TTYPEMATCHPOLICY = TSubSetMatchPolicy, typename TFLAGSMATCHPOLICY = TSuperSetMatchPolicy> |
|
204 struct TMatchPolicy |
|
205 { |
|
206 inline static TBool Match(const TClientType& aType, const TClientType& aMatch) |
|
207 { |
|
208 return TTYPEMATCHPOLICY::Match(aType.Type(),aMatch.Type()) |
|
209 && TFLAGSMATCHPOLICY::Match(aType.Flags(),aMatch.Flags()); |
|
210 } |
|
211 }; |
|
212 |
|
213 template <typename TINCMATCHPOLICY = TMatchPolicy<TSubSetMatchPolicy,TSuperSetMatchPolicy>, typename TEXCMATCHPOLICY = TMatchPolicy<TExactMatchPolicy,TExactMatchPolicy> > |
|
214 struct TTypeMatchPolicy |
|
215 { |
|
216 inline static TBool Match(const TClientType& aType, const TClientType& aInclude, const TClientType& aExclude) |
|
217 { |
|
218 TBool inc = TINCMATCHPOLICY::Match(aType, aInclude); |
|
219 TBool exc = aExclude.IsNull() || !TEXCMATCHPOLICY::Match(aType, aExclude); |
|
220 return inc && exc; |
|
221 } |
|
222 }; |
|
223 |
|
224 //We could be using partially specialised typedefs here, |
|
225 //if they only were supported by C++ at the time of writing this code... |
|
226 // INCType | Type Flag EXCType | Type Flag |
|
227 // ---------------------------------------------- ------------------------------------------------- |
|
228 typedef TTypeMatchPolicy<TMatchPolicy<TSubSetMatchPolicy, TSuperSetMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TDefaultClientMatchPolicy; |
|
229 typedef TTypeMatchPolicy<TMatchPolicy<TSuperSetMatchPolicy,TSuperSetMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TFlagsOnlyClientMatchPolicy; |
|
230 typedef TTypeMatchPolicy<TMatchPolicy<TSubSetMatchPolicy, TNoMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TExcludeTypeAndFlagClientMatchPolicy; |
|
231 typedef TTypeMatchPolicy<TMatchPolicy<TSubSetMatchPolicy, TExactOrAnyMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TExactOrAnyIncludeFlagsClientMatchPolicy; |
|
232 |
|
233 |
|
234 class RClientInterface |
|
235 /* |
|
236 Represents an opaque recipient of messages with no assumptions about its |
|
237 type (i.e.: it's not necesserilly a node and the only thing known about it, is its |
|
238 TRuntimeCtxId). Relations with such recipients should be implemented by declaring |
|
239 RClientInterface as members. |
|
240 @see RNodeInterface |
|
241 */ |
|
242 { |
|
243 public: |
|
244 IMPORT_C RClientInterface(); |
|
245 IMPORT_C virtual ~RClientInterface(); //Derived types may be used via base ptrs |
|
246 IMPORT_C void Open(const TRuntimeCtxId& aPostTo, MTransportSender* aSender = NULL); |
|
247 IMPORT_C void Close(); // stomp members |
|
248 IMPORT_C TBool operator==(const TRuntimeCtxId& aRHS) const; |
|
249 IMPORT_C TBool operator==(const RClientInterface& aRHS) const; |
|
250 |
|
251 IMPORT_C TBool IsOpen() const; |
|
252 |
|
253 inline const TRuntimeCtxId& RecipientId() const |
|
254 { |
|
255 return *reinterpret_cast<const TRuntimeCtxId*>(iRecipientAddress); |
|
256 } |
|
257 |
|
258 IMPORT_C static void OpenPostMessageClose(const TRuntimeCtxId& aPostFrom, const TRuntimeCtxId& aPostTo, const TSignalBase& aMessage); |
|
259 IMPORT_C void PostMessage(const TRuntimeCtxId& aPostFrom, const TSignalBase& aMessage) const; |
|
260 |
|
261 protected: |
|
262 void PostMessage(const TRuntimeCtxId& aPostFrom, const TRuntimeCtxId& aPostTo, const TSignalBase& aMessage) const; |
|
263 inline TRuntimeCtxId& RecipientRef() |
|
264 { |
|
265 return *reinterpret_cast<TRuntimeCtxId*>(iRecipientAddress); |
|
266 } |
|
267 |
|
268 inline const TRuntimeCtxId& RecipientRef() const |
|
269 { |
|
270 return *reinterpret_cast<const TRuntimeCtxId*>(iRecipientAddress); |
|
271 } |
|
272 |
|
273 private: |
|
274 MTransportSender* iTransportSender; |
|
275 TUint8 iRecipientAddress[__Align8(TRuntimeCtxId::KMaxInlineAddressSize)]; |
|
276 }; |
|
277 |
|
278 |
|
279 class RNodeInterface : public RClientInterface |
|
280 /* |
|
281 RNodeInterface represents a relation with a node (ANode). It does so by: |
|
282 - storing the node's address (TNodeId) |
|
283 - collecting informations about the node (::Type & ::Flags). |
|
284 Classes (typically nodes) should implement relations with another nodes |
|
285 by declaring RNodeInterface as members. |
|
286 @see TClientType |
|
287 */ |
|
288 { |
|
289 friend class TClientIterBase; |
|
290 |
|
291 public: |
|
292 IMPORT_C void Open(TNodeId aPostTo, const TClientType& aClientType = TClientType::NullType(), MTransportSender* aSender = NULL); |
|
293 IMPORT_C void Close(); |
|
294 IMPORT_C TBool operator==(const RNodeInterface& aRHS) const; |
|
295 |
|
296 inline TBool operator==(const TRuntimeCtxId& aRHS) const |
|
297 { |
|
298 return RClientInterface::operator==(aRHS); |
|
299 } |
|
300 |
|
301 IMPORT_C void PostMessage(const TRuntimeCtxId& aPostFrom, const TNodeId::TRemainder& aPostTo, const TSignalBase& aMessage) const; |
|
302 inline void PostMessage(const TRuntimeCtxId& aPostFrom, const TSignalBase& aMessage) const |
|
303 { |
|
304 #ifdef SYMBIAN_TRACE_ENABLE |
|
305 if(Flags() & TClientType::ELeaving) |
|
306 { |
|
307 NM_LOG_START_BLOCK(KNodeMessagesSubTag, _L8("ERROR: Post while node is leaving")); |
|
308 NM_LOG_ADDRESS_EXT(KNodeMessagesSubTag, aPostFrom, _L8("From:")); |
|
309 NM_LOG_ADDRESS_EXT(KNodeMessagesSubTag, RecipientId(), _L8("To:")); |
|
310 NM_LOG_MESSAGE_EXT(KNodeMessagesSubTag, aMessage, _L8("Msg:")); |
|
311 NM_LOG_END_BLOCK(KNodeMessagesSubTag, KNullDesC8); |
|
312 } |
|
313 #endif |
|
314 __ASSERT_DEBUG(!(Flags() & TClientType::ELeaving), User::Panic(KSpecAssert_ElemNodeMessIntH, 1)); //OOOOOPS! What are you doing?? |
|
315 RClientInterface::PostMessage(aPostFrom, aMessage); |
|
316 } |
|
317 |
|
318 inline const TNodeId& RecipientId() const |
|
319 { |
|
320 return address_cast<TNodeId>(RClientInterface::RecipientId()); |
|
321 } |
|
322 |
|
323 TClientType& ClientType() |
|
324 { |
|
325 return iClientType; |
|
326 } |
|
327 |
|
328 TUint32 Type() const |
|
329 { |
|
330 return iClientType.Type(); |
|
331 } |
|
332 |
|
333 TUint32 Flags() const |
|
334 { |
|
335 return iClientType.Flags(); |
|
336 } |
|
337 |
|
338 TUint32 SetFlags(TUint32 aFlags) |
|
339 { |
|
340 #if defined(_DEBUG) && defined(NM_LOG_FLAG_SETTINGS) |
|
341 // Note that this generates quite alot of logging, hence is not turned on by default. |
|
342 // Note also that (a minority of) flag setting may also take place in TNodePeerId. |
|
343 const TUint32 oldFlags = Flags(); |
|
344 const TUint32 newFlags = iClientType.SetFlags(aFlags); |
|
345 if (oldFlags != newFlags) |
|
346 { |
|
347 NM_LOG((KNodeMessagesSubTag, _L8("RNI::SetFlags(%x) ANode=%08x, %x->%x"), aFlags, &RecipientId().Node(), oldFlags, newFlags)); |
|
348 } |
|
349 return newFlags; |
|
350 #else |
|
351 return iClientType.SetFlags(aFlags); |
|
352 #endif |
|
353 } |
|
354 |
|
355 TUint32 ClearFlags(TUint32 aFlags) |
|
356 { |
|
357 #if defined(_DEBUG) && defined(NM_LOG_FLAG_SETTINGS) |
|
358 const TUint32 oldFlags = Flags(); |
|
359 const TUint32 newFlags = iClientType.ClearFlags(aFlags); |
|
360 if (oldFlags != newFlags) |
|
361 { |
|
362 NM_LOG((KNodeMessagesSubTag, _L8("RNI::ClearFlags(%x) ANode=%08x, %x->%x"), aFlags, &RecipientId().Node(), oldFlags, newFlags)); |
|
363 } |
|
364 return newFlags; |
|
365 #else |
|
366 return iClientType.ClearFlags(aFlags); |
|
367 #endif |
|
368 } |
|
369 |
|
370 protected: |
|
371 TClientType iClientType; |
|
372 }; |
|
373 |
|
374 class RRequestOriginator |
|
375 /* |
|
376 RRequestOriginator is a helper class that ackowledges the very common scenario |
|
377 where an activity running at a remote node sends a request and that request |
|
378 needs to be replied to. RRequestOriginator is associated with a node (holds |
|
379 a reference to RNodeInterface) as well as stores the TNodeId::TReminder of |
|
380 the address in order to identify the activity running at that node. |
|
381 */ |
|
382 { |
|
383 public: |
|
384 IMPORT_C TInt Open(RNodeInterface& aNode, const TRuntimeCtxId& aRequestOriginator); |
|
385 IMPORT_C void Open(RRequestOriginator& aOriginalRequest); |
|
386 IMPORT_C void Close(); |
|
387 |
|
388 IMPORT_C TBool operator==(const RRequestOriginator& aRHS) const; |
|
389 IMPORT_C TBool operator==(const TRuntimeCtxId& aRHS) const; |
|
390 |
|
391 IMPORT_C TBool IsOpen() const; |
|
392 |
|
393 Messages::RNodeInterface& Node() |
|
394 { |
|
395 __ASSERT_DEBUG(IsOpen(), User::Panic(Messages::KMessagesPanic,Messages::EClientNotValidPanic)); |
|
396 return *iNode; |
|
397 } |
|
398 const Messages::RNodeInterface& Node() const |
|
399 { |
|
400 __ASSERT_DEBUG(IsOpen(), User::Panic(Messages::KMessagesPanic,Messages::EClientNotValidPanic)); |
|
401 return *iNode; |
|
402 } |
|
403 |
|
404 Messages::TNodeId::TRemainder& Remainder() |
|
405 { |
|
406 Node(); //Make sure 'this' is openned |
|
407 return iRemainder; |
|
408 } |
|
409 const Messages::TNodeId::TRemainder& Remainder() const |
|
410 { |
|
411 Node(); //Make sure 'this' is openned |
|
412 return iRemainder; |
|
413 } |
|
414 |
|
415 |
|
416 IMPORT_C void PostMessage(const TRuntimeCtxId& aPostFrom, const TSignalBase& aMessage) const; |
|
417 IMPORT_C void ReplyTo(const TRuntimeCtxId& aReplyFrom, const TSignalBase& aMessage); |
|
418 |
|
419 private: |
|
420 Messages::TNodeId::TRemainder iRemainder; |
|
421 Messages::RNodeInterface* iNode; |
|
422 }; |
|
423 |
|
424 // |
|
425 // TClientIterBase |
|
426 class TClientIterBase |
|
427 { |
|
428 public: |
|
429 typedef RPointerArray<RNodeInterface> TClientArray; |
|
430 |
|
431 public: |
|
432 inline RNodeInterface* operator++(TInt /*aInd*/) //-postfix |
|
433 { |
|
434 RNodeInterface* cli = Find(iIndex, +1, 1); |
|
435 iIndex++; |
|
436 return cli; |
|
437 } |
|
438 |
|
439 inline RNodeInterface* operator++() //-prefix |
|
440 { |
|
441 ++iIndex; |
|
442 return Find(iIndex, +1, 1); |
|
443 } |
|
444 |
|
445 inline RNodeInterface* operator--(TInt /*aInd*/) //-postfix |
|
446 { |
|
447 RNodeInterface* cli = Find(iIndex, -1, 1); |
|
448 iIndex--; |
|
449 return cli; |
|
450 } |
|
451 |
|
452 IMPORT_C RNodeInterface* operator[](TInt aInd); |
|
453 |
|
454 inline RNodeInterface* operator*() |
|
455 { |
|
456 return Find(iIndex, +1, 0); |
|
457 } |
|
458 |
|
459 void SetToLast() |
|
460 { |
|
461 iIndex = iClients.Count() - 1; |
|
462 } |
|
463 |
|
464 void Reset() |
|
465 { |
|
466 iIndex = 0; |
|
467 } |
|
468 |
|
469 protected: |
|
470 virtual TBool TypeMatch(RNodeInterface& aClient) const = 0; |
|
471 explicit TClientIterBase(const RPointerArray<RNodeInterface>& aClients) |
|
472 : iClients(aClients), |
|
473 iIndex(0) |
|
474 { |
|
475 } |
|
476 |
|
477 IMPORT_C RNodeInterface* Find(TInt& aInd, TInt aDir, TInt aCount); |
|
478 const RPointerArray<RNodeInterface>& iClients; |
|
479 TInt iIndex; |
|
480 }; |
|
481 |
|
482 // |
|
483 // TClientIter |
|
484 template<class TTYPEMATCHPOLICY = TDefaultClientMatchPolicy> |
|
485 class TClientIter : public TClientIterBase |
|
486 { |
|
487 public: |
|
488 explicit TClientIter(const RPointerArray<RNodeInterface>& aClients, const TClientType& aInclude, const TClientType& aExclude = TClientType::NullType()) |
|
489 : TClientIterBase(aClients), iInclude(aInclude), iExclude(aExclude) {}; |
|
490 |
|
491 private: |
|
492 virtual TBool TypeMatch(RNodeInterface& aClient) const |
|
493 { |
|
494 return TTYPEMATCHPOLICY::Match(aClient.ClientType(), iInclude, iExclude); |
|
495 } |
|
496 |
|
497 TClientType iInclude; |
|
498 TClientType iExclude; |
|
499 }; |
|
500 |
|
501 |
|
502 } //namespace Messages |
|
503 |
|
504 #endif |
|
505 //SYMBIAN_NM_INTERFACES_H |
|
506 |
|
507 |