|
1 // Copyright (c) 2004-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 // timeout.h - timer manager |
|
15 // Timer Manager. |
|
16 // |
|
17 |
|
18 |
|
19 |
|
20 /** |
|
21 @file timeout.h |
|
22 @publishedPartner |
|
23 @released |
|
24 */ |
|
25 |
|
26 #ifndef __TIMEOUT_H__ |
|
27 #define __TIMEOUT_H__ |
|
28 |
|
29 #include <e32base.h> |
|
30 #include "apibase.h" |
|
31 |
|
32 class RTimeout; |
|
33 class MTimeoutManager; |
|
34 |
|
35 // TimeoutFactory |
|
36 // ************** |
|
37 |
|
38 class TimeoutFactory |
|
39 /** |
|
40 * Factory for creating MTimeoutManager instance(s). |
|
41 * |
|
42 * TimeoutFactory is not a class that can be instantiated! It only declares |
|
43 * static methods, and only publicly available method (NewL) is the one that |
|
44 * creates an instance of a timeout manager and returns a reference to the |
|
45 * interface class (MTimeoutManager). |
|
46 * |
|
47 * @publishedPartner |
|
48 * @released |
|
49 */ |
|
50 { |
|
51 friend class RTimeout; |
|
52 public: |
|
53 IMPORT_C static MTimeoutManager *NewL(TUint aUnit = 1, TAny *aPtr = 0, TInt aPriority = 0); |
|
54 private: |
|
55 IMPORT_C static void Cancel(RTimeout &aLink); |
|
56 IMPORT_C static TBool IsActive(const RTimeout &aLink); |
|
57 }; |
|
58 |
|
59 // MTimeoutManager |
|
60 // *************** |
|
61 |
|
62 class MTimeoutManager : public MInetBase |
|
63 /** |
|
64 * Implementation of "delta queue" timeout manager. |
|
65 * |
|
66 * The timeout manager provides a timeout callback service |
|
67 * for any object. An object using the timeout service only |
|
68 * needs to have member variable of RTimeout and define the |
|
69 * timeout linkage (TimeoutLinkage) for redirecting the |
|
70 * timeout callback to a real function of some object. |
|
71 * |
|
72 * The same time manager can be used for different object |
|
73 * classes. A component can use single timeout manager |
|
74 * instance for all of its objects: |
|
75 * |
|
76 * -# Create timeout manager using TimeoutFactory::NewL |
|
77 * -# Objects, which need the timeout callback, declare |
|
78 * the RTimeout member variable and the appropriate |
|
79 * linkage (TimeoutLinkage). |
|
80 * -# The timeout callback for a object is requested either |
|
81 * by RTimeout::Set or MTimeoutManager::Set. The set |
|
82 * implicitly cancels previous timeout, if active. |
|
83 * -# RTimeout::Cancel cancels pending timeout, if any |
|
84 * is active. |
|
85 * |
|
86 * Destructions: |
|
87 * -# When an object with RTimeout member(s) is destroyed, |
|
88 * the destructor of this object should include a |
|
89 * RTimeout::Cancel() for the member variable(s). |
|
90 * -# The timeout manager must be deleted, as any normal |
|
91 * allocated object. All pending timeouts are silently |
|
92 * cancelled (no expire call will happen for them). |
|
93 * |
|
94 * The timeout manager maintains an ordered queue of pending timeouts. |
|
95 * The next object to expire is always the first in the list, and |
|
96 * the timeout manager sets up an internal timer event (RTimer::After) |
|
97 * to happen based on the first object. |
|
98 * |
|
99 * To create an instance of a timeout manager, use TimeoutFactory::NewL. |
|
100 * |
|
101 * @publishedPartner |
|
102 * @released |
|
103 */ |
|
104 { |
|
105 public: |
|
106 /** |
|
107 * Destructor. |
|
108 * |
|
109 * Even though this is a "mixin" class, the entity that creates |
|
110 * it through the TimeoutFactory::NewL() is expected to delete |
|
111 * this manager using the returned pointer. |
|
112 */ |
|
113 virtual ~MTimeoutManager() {}; |
|
114 /** |
|
115 * Activate timeout callback after the specified time. |
|
116 * |
|
117 * Set a timeout for an object (any previous timeout setting for |
|
118 * this object is silently removed, no Expired callback will |
|
119 * occur for that). The timeout (aTime) value interpretation is |
|
120 * dependent on the aUnit parameter specified for the manager, |
|
121 * when it was created (see TimeoutFactory::NewL). |
|
122 * |
|
123 * @param aLink the timeout handle within the object |
|
124 * @param aTime the time (in fraction of second units). |
|
125 */ |
|
126 virtual void Set(RTimeout &aLink, TUint aTime) = 0; |
|
127 }; |
|
128 |
|
129 // TimeoutCallback |
|
130 // *************** |
|
131 /** |
|
132 * The callback template. |
|
133 * |
|
134 * If the timer expires, the timeout callback is called. |
|
135 * |
|
136 * @param aLink |
|
137 * The timeout handle that expired, |
|
138 * @param aNow |
|
139 * The current time (to which the expiry is based on. |
|
140 * @param aPtr |
|
141 * The aPtr paramater given in timeout manager instantiation. |
|
142 * |
|
143 * @publishedPartner |
|
144 * @released |
|
145 */ |
|
146 typedef void (*TimeoutCallback)(RTimeout &aLink, const TTime &aNow, TAny *aPtr); |
|
147 |
|
148 |
|
149 // RTimeout |
|
150 // ******** |
|
151 class RTimeout |
|
152 /** |
|
153 * The timeout handle. |
|
154 * |
|
155 * This can be a member of any object that needs timeout events. |
|
156 * |
|
157 * The RTimeout can be used as a base for derived classes. |
|
158 * |
|
159 * @publishedPartner |
|
160 * @released |
|
161 */ |
|
162 { |
|
163 friend class CTimeoutManager; |
|
164 friend class TimeoutFactory; |
|
165 public: |
|
166 RTimeout(TimeoutCallback aCallback) : iDelta(0), iExpired(aCallback) |
|
167 /** |
|
168 * Contructor. |
|
169 * |
|
170 * @param aCallback the expire callback function |
|
171 */ |
|
172 { |
|
173 // Can't use 'this' as initializer, so following is required. |
|
174 iNext = this; |
|
175 iPrev = this; |
|
176 } |
|
177 |
|
178 inline void Set(MTimeoutManager *aMgr, TUint aTime) |
|
179 /** |
|
180 * Activate timeout callback after the specified time. |
|
181 * |
|
182 * Just an alternate way of calling MTimeoutManager::Set. |
|
183 * |
|
184 * @param aMgr The timeout manager. |
|
185 * @param aTime The time (in fraction of second units). |
|
186 */ |
|
187 { |
|
188 aMgr->Set(*this, aTime); |
|
189 } |
|
190 inline TBool IsActive() const |
|
191 /** |
|
192 * Tests if the timeout is active. |
|
193 * @return |
|
194 * @li ETrue, if timeout is active |
|
195 * @li EFalse, if timeout is not active |
|
196 * |
|
197 * @note |
|
198 * It is always safe to just add the link to a new time manager. |
|
199 * Add will implicitly cancel any previous setting, if such exists. |
|
200 */ |
|
201 { |
|
202 return TimeoutFactory::IsActive(*this); |
|
203 } |
|
204 inline void Cancel() |
|
205 /** |
|
206 * Cancel timeout. |
|
207 * |
|
208 * Cancel removes the timeout (if any) from this link. |
|
209 * No Expired() call will happen as a result of this. |
|
210 */ |
|
211 { |
|
212 TimeoutFactory::Cancel(*this); |
|
213 } |
|
214 private: |
|
215 RTimeout *iPrev; |
|
216 RTimeout *iNext; |
|
217 TUint iDelta; |
|
218 const TimeoutCallback iExpired; |
|
219 }; |
|
220 |
|
221 |
|
222 // ************** |
|
223 // TimeoutLinkage |
|
224 // ************** |
|
225 template <class T, int Offset> |
|
226 class TimeoutLinkage |
|
227 /** |
|
228 * Access "parent" class based on the RTimeout member offset. |
|
229 * |
|
230 * This is a base template class to convert the link reference into |
|
231 * "parent" class refeference. This is just a convenience |
|
232 * template and other solutions for defining the the |
|
233 * "expired" callback for RTimeout can also be used. |
|
234 * |
|
235 * A simple use example: |
|
236 @code |
|
237 class CSome |
|
238 { |
|
239 |
|
240 CSome(aCallback) : iTimeout(aCallback) {}; |
|
241 ~CSome() { iTimeout.Cancel(); } |
|
242 Timeout(); // A method to handle the timeout of CSome |
|
243 public: |
|
244 RTimeout iTimeout; |
|
245 }; |
|
246 |
|
247 class SomeLinkage : public TimeoutLinkage<CSome, _FOFF(CSome, iTimeout)> |
|
248 { |
|
249 public: |
|
250 static void Expired(RTimeout &aLink, const TTime & aNow, TAny *aPtr) |
|
251 { |
|
252 Object(aLink)->Timeout(); |
|
253 } |
|
254 }; |
|
255 @endcode |
|
256 * All of the above can be in the CSome header file, and instances of CSome can now just |
|
257 * be created as |
|
258 @code |
|
259 MTimeoutManager *tMgr = TimeoutFactory::NewL(1); // unit = 1s |
|
260 ... |
|
261 CSome x = new CSome(SomeLinkage:Expired); |
|
262 ... |
|
263 x->iTimeout.Set(tMgr, 10); // request timeout after 10s. |
|
264 ... |
|
265 // when not needed, just delete |
|
266 delete x; |
|
267 delete tMgr; |
|
268 @endcode |
|
269 * and the CSome Timeout() method will be called after 10s, unless |
|
270 * cancelled. |
|
271 * |
|
272 * Instead of using the Timeout in the objects directly, the aPtr parameter |
|
273 * of Expired could be an address of a manager type instance, |
|
274 * which handles objects of this type. The object itself might not have |
|
275 * any use of the Expired call and it should be passed to the manager. This can |
|
276 * be realised by defining the linkage Expired as follows (for example) |
|
277 @code |
|
278 static void Expired(RTimeoutLink &aLink, const TTime &aNow, TAny *aPtr) |
|
279 { |
|
280 ((CSomeManager *)aPtr)->Timeout(Object(aLink), aNow); |
|
281 } |
|
282 @endcode |
|
283 * @publishedPartner |
|
284 * @released |
|
285 */ |
|
286 { |
|
287 protected: |
|
288 static inline T *Object(RTimeout &aLink) |
|
289 /** |
|
290 * Gets the "parent object" of RTimeout member. |
|
291 * |
|
292 * Based on the offset of the RTimeout member, typecast the |
|
293 * adjusted pointer to the "parent type", and return the |
|
294 * pointer. |
|
295 * |
|
296 * @param aLink The timeout handle. |
|
297 * @return The object. |
|
298 */ |
|
299 { |
|
300 return ((T *)((char *)(&aLink) - Offset)); |
|
301 } |
|
302 }; |
|
303 |
|
304 #endif |