|
1 /* |
|
2 * Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #ifndef UNIQUEINSTANCE_H_ |
|
20 #define UNIQUEINSTANCE_H_ |
|
21 |
|
22 #include "UniqueInstanceBase.h" |
|
23 |
|
24 // A user may only create and destroy the repository. All access is through the |
|
25 // RUniqueInstance class. |
|
26 // |
|
27 // Please note : Deleting the repository is unsafe unless all of its owned |
|
28 // objects have been destroyed or relinquished. If objects exist in the repository |
|
29 // (and provided that no RUniqueInstance objects have leaked) it follows that |
|
30 // there must be RUniqueInstance objects around that still reference these objects. |
|
31 // These RUniqueInstances will at some point try to access the repository to |
|
32 // relinquish or destroy these objects, but it will have been deleted! Therefore |
|
33 // the destructor panics if there are any objects in the repository. |
|
34 // |
|
35 // The compare function and copy function must co-operate like this: |
|
36 // A) aCompare is a total order. That is, for all valid objects of type T t, u and v: |
|
37 // i) aCompare(t, t) == 0 (idempotency) |
|
38 // ii) if aCompare(t, u) < 0 then aCompare(u, t) > 0 (associativity) |
|
39 // iii)if aCompare(t, u) < 0 and aCompare(u, v) < 0 then aCompare(t, v) < 0 |
|
40 // (transitivity) |
|
41 // B) aCopyL always produces objects that compare equal to the arguments that |
|
42 // produced them, that is for all valid objects of type T t: |
|
43 // aCompare(t, aCopyL(t, sizeof(T))) == 0 (ignoring the memory leak!) |
|
44 // If these conditions are not met, the behaviour of the repository is undefined. |
|
45 // If the type does not own anything and does not have variable length, the |
|
46 // copy and delete functions can be omitted. |
|
47 // |
|
48 // The operation of the repository and its clients is not thread safe. |
|
49 // |
|
50 // For aMaxLinks give half the log(base 2) of the expected maximum size of the |
|
51 // repository. So for a repository of size 256, use 4. For size 65535 use 8. For |
|
52 // 16777216 use 12. |
|
53 |
|
54 /** |
|
55 Store of objects that coalesces repeated instances. |
|
56 |
|
57 @since App-frameworks6.1 |
|
58 @internalComponent |
|
59 */ |
|
60 template <typename T> class CUniqueInstanceRepository |
|
61 : public UniqueInstance::CUniqueInstanceRepositoryBase |
|
62 |
|
63 { |
|
64 public: |
|
65 |
|
66 // typical implementation might be: |
|
67 // void CompareT(const T* aL, const T* aR) |
|
68 // { |
|
69 // if (*aL == *aR) |
|
70 // return 0; |
|
71 // if (*aL < *aR) |
|
72 // return -1; |
|
73 // return 1; |
|
74 // } |
|
75 typedef TInt TCompareFnType(const T*, const T*); |
|
76 |
|
77 // typical implementation might be: |
|
78 // void DeleteT(T* aDestroy) |
|
79 // { |
|
80 // delete aDestroy; |
|
81 // } |
|
82 typedef void TDeleteFnType(T* aObjectToBeDestroyed); |
|
83 |
|
84 // typical implementation might be: |
|
85 // T* CopyT(const T* aSrc, TInt aOffset, TInt) |
|
86 // { |
|
87 // return new(ELeave) T(*aSrc); |
|
88 // } |
|
89 typedef T* TCopyFnTypeL(const T* aTToBeCopied, TInt aSizeOfT); |
|
90 |
|
91 /** |
|
92 * Creates a new empty repository. aCompare must define a total order on |
|
93 * objects that may be added to the repository. In other words |
|
94 * aCompare(a,b) == 0 iff a and b are equivalent, aCompare(a,b) < 0 |
|
95 * iff aCompare(a,b) > 0, aCompare(a,b) < 0 iff aCompare(b,a) < 0 and |
|
96 * aCompare(a,b) < 0 && aCompare(b,c) < 0 implies that aCompare(a,c) < 0. |
|
97 * aDelete(a) deletes a and aCopyL(a) generates a new object such that |
|
98 * aCompare(aCopyL(a),a) == 0. |
|
99 * aMaxLinks concerns the space against speed tradeoff of the |
|
100 * implementation. It should be a number greater than half log2 of the |
|
101 * expected maximum size of the repository. |
|
102 */ |
|
103 static inline CUniqueInstanceRepository<T>* NewL(TCompareFnType* aCompare, |
|
104 TDeleteFnType* aDelete, TCopyFnTypeL* aCopyL, TInt aMaxLinks = 10); |
|
105 static inline CUniqueInstanceRepository<T>* NewLC(TCompareFnType* aCompare, |
|
106 TDeleteFnType* aDelete, TCopyFnTypeL* aCopyL, TInt aMaxLinks = 10); |
|
107 /** |
|
108 * Creates a new empty repository with aDelete(a) simply freeing memory |
|
109 * at a and aCopyL(a) simply bitwise copying the memory occupied by a. |
|
110 * This is suitable only if T has no destructor and only the automatic |
|
111 * copy constructor. |
|
112 */ |
|
113 static inline CUniqueInstanceRepository<T>* NewL(TCompareFnType* aCompare, |
|
114 TInt aMaxLinks = 10); |
|
115 static inline CUniqueInstanceRepository<T>* NewLC(TCompareFnType* aCompare, |
|
116 TInt aMaxLinks = 10); |
|
117 private: |
|
118 CUniqueInstanceRepository() {} |
|
119 }; |
|
120 |
|
121 /** |
|
122 Specialization for the odd semantics of TDes. Copy/Delete/Compare functions |
|
123 are provided free. |
|
124 |
|
125 @since App-frameworks6.1 |
|
126 @internalComponent |
|
127 */ |
|
128 template <> class CUniqueInstanceRepository<TDes> |
|
129 : public UniqueInstance::CUniqueInstanceRepositoryBase |
|
130 |
|
131 { |
|
132 CUniqueInstanceRepository() {} |
|
133 static void* DesCopyL(void*, TInt); |
|
134 static TInt DesCompare(void*, void*); |
|
135 static void DesDelete(void*); |
|
136 public: |
|
137 static inline CUniqueInstanceRepository<TDes>* NewL(TInt aMaxLinks = 10); |
|
138 static inline CUniqueInstanceRepository<TDes>* NewLC(TInt aMaxLinks = 10); |
|
139 }; |
|
140 |
|
141 /** |
|
142 Client of a CUniqueInstanceRepository. |
|
143 Holds a single object, which may be shared. |
|
144 |
|
145 @since App-frameworks6.1 |
|
146 @internalComponent |
|
147 */ |
|
148 template <typename T> class RUniqueInstance |
|
149 |
|
150 { |
|
151 public: |
|
152 inline explicit RUniqueInstance(CUniqueInstanceRepository<T>& aRepository) |
|
153 : iImpl(aRepository) {} |
|
154 /** |
|
155 * Destructor. In debug builds this asserts that no object is owned. |
|
156 */ |
|
157 inline ~RUniqueInstance() {} |
|
158 |
|
159 /** |
|
160 * Registers the argument as a unique instance, to be referenced by this |
|
161 * RUniqueInstance. Any previously owned object is destroyed. |
|
162 */ |
|
163 inline void TakeL(T* aToAdd); |
|
164 /** |
|
165 * Makes a copy of the argument, as a unique instance. The argument is |
|
166 * still owned by the caller |
|
167 */ |
|
168 inline void TakeCopyL(const T* aToCopy); |
|
169 /** |
|
170 * Returns a pointer to the referenced object without passing ownership |
|
171 */ |
|
172 inline const T* Peek() const; |
|
173 /** |
|
174 * Makes another instance of the same object: both have ownership |
|
175 */ |
|
176 inline void CopyTo(RUniqueInstance<T>& aOther) const; |
|
177 /** |
|
178 * Pass ownership of the owned object to another RUniqueInstance. |
|
179 * This object may not be referenced through this RUniqueInstance any |
|
180 * more, only through aOther. |
|
181 */ |
|
182 inline void MoveTo(RUniqueInstance<T>& aOther); |
|
183 /** |
|
184 * Relinquishes ownership of the object to the caller. The object is |
|
185 * not destroyed. It may not be referenced through this RUniqueInstance |
|
186 * any more. The pointer returned may be different from that passed |
|
187 * to TakeL() or returned from Peek() |
|
188 */ |
|
189 inline T* DropL(); |
|
190 /** |
|
191 * Releases the owned object. |
|
192 */ |
|
193 inline void Close(); |
|
194 |
|
195 private: |
|
196 UniqueInstance::RInstanceImpl iImpl; |
|
197 }; |
|
198 |
|
199 /** |
|
200 Specialization of RUniqueInstance for the odd semantics of TDes. |
|
201 Any descriptor that needs ownership to be passed around is an HBufC. |
|
202 Any time a copy or view over a descriptor is required, a const TDesC |
|
203 is used. Please note the different signature of NewL and NewLC. This is |
|
204 because copy, delete and compare functions are provided for free. |
|
205 |
|
206 @since App-frameworks6.1 |
|
207 @internalComponent |
|
208 */ |
|
209 TEMPLATE_SPECIALIZATION class RUniqueInstance<TDes> |
|
210 |
|
211 { |
|
212 public: |
|
213 inline explicit RUniqueInstance(CUniqueInstanceRepository<TDes>& aRepository) |
|
214 : iImpl(aRepository) {} |
|
215 inline ~RUniqueInstance() {} |
|
216 inline void TakeL(HBufC* aToAdd); |
|
217 inline void TakeCopyL(const TDesC* aToCopy); |
|
218 inline const TDesC* Peek() const; |
|
219 inline void CopyTo(RUniqueInstance<TDes>& aOther) const; |
|
220 inline void MoveTo(RUniqueInstance<TDes>& aOther); |
|
221 inline HBufC* DropL(); |
|
222 inline void Close(); |
|
223 |
|
224 private: |
|
225 UniqueInstance::RInstanceImpl iImpl; |
|
226 }; |
|
227 |
|
228 template <typename T> |
|
229 inline CUniqueInstanceRepository<T>* CUniqueInstanceRepository<T>::NewLC( |
|
230 typename CUniqueInstanceRepository<T>::TCompareFnType* aCompare, |
|
231 typename CUniqueInstanceRepository<T>::TDeleteFnType* aDelete, |
|
232 typename CUniqueInstanceRepository<T>::TCopyFnTypeL* aCopyL, TInt aMaxLinks) |
|
233 { |
|
234 CUniqueInstanceRepository<T>* that = new(ELeave) CUniqueInstanceRepository<T>; |
|
235 CleanupStack::PushL(that); |
|
236 that->ConstructL(reinterpret_cast<UniqueInstance::TCompareFn*>(aCompare), |
|
237 reinterpret_cast<UniqueInstance::TDeleteFn*>(aDelete), |
|
238 reinterpret_cast<UniqueInstance::TCopyFnL*>(aCopyL), aMaxLinks, |
|
239 sizeof(T)); |
|
240 return that; |
|
241 } |
|
242 |
|
243 template <typename T> |
|
244 inline CUniqueInstanceRepository<T>* CUniqueInstanceRepository<T>::NewL( |
|
245 typename CUniqueInstanceRepository<T>::TCompareFnType* aComp, |
|
246 typename CUniqueInstanceRepository<T>::TDeleteFnType* aDel, |
|
247 typename CUniqueInstanceRepository<T>::TCopyFnTypeL* aCopyL, TInt aMaxLinks) |
|
248 { |
|
249 CUniqueInstanceRepository<T>* that = NewLC(aComp, aDel, aCopyL, aMaxLinks); |
|
250 CleanupStack::Pop(that); |
|
251 return that; |
|
252 } |
|
253 |
|
254 template <typename T> |
|
255 inline CUniqueInstanceRepository<T>* CUniqueInstanceRepository<T>::NewLC( |
|
256 typename CUniqueInstanceRepository<T>::TCompareFnType* aCompare, TInt aMaxLinks) |
|
257 { |
|
258 CUniqueInstanceRepository<T>* that = new(ELeave) CUniqueInstanceRepository<T>; |
|
259 CleanupStack::PushL(that); |
|
260 that->ConstructL(reinterpret_cast<UniqueInstance::TCompareFn*>(aCompare), |
|
261 DumbDelete, DumbCopyL, aMaxLinks, |
|
262 sizeof(T)); |
|
263 return that; |
|
264 } |
|
265 |
|
266 template <typename T> |
|
267 inline CUniqueInstanceRepository<T>* CUniqueInstanceRepository<T>::NewL( |
|
268 typename CUniqueInstanceRepository<T>::TCompareFnType* aComp, TInt aMaxLinks) |
|
269 { |
|
270 CUniqueInstanceRepository<T>* that = NewLC(aComp, aMaxLinks); |
|
271 CleanupStack::Pop(that); |
|
272 return that; |
|
273 } |
|
274 |
|
275 inline CUniqueInstanceRepository<TDes>* CUniqueInstanceRepository<TDes>::NewLC( |
|
276 TInt aMaxLinks) |
|
277 { |
|
278 CUniqueInstanceRepository<TDes>* that = new(ELeave) CUniqueInstanceRepository<TDes>; |
|
279 CleanupStack::PushL(that); |
|
280 that->ConstructL(DesCompare, DesDelete, DesCopyL, aMaxLinks, 1); |
|
281 return that; |
|
282 } |
|
283 |
|
284 inline CUniqueInstanceRepository<TDes>* CUniqueInstanceRepository<TDes>::NewL( |
|
285 TInt aMaxLinks) |
|
286 { |
|
287 CUniqueInstanceRepository<TDes>* that = NewLC(aMaxLinks); |
|
288 CleanupStack::Pop(that); |
|
289 return that; |
|
290 } |
|
291 |
|
292 /////////////////////////////// |
|
293 // // |
|
294 // RUniqueInstance inlines // |
|
295 // // |
|
296 /////////////////////////////// |
|
297 |
|
298 template <typename T> inline |
|
299 void RUniqueInstance<T>::TakeL(T* aToAdd) |
|
300 { iImpl.TakeL(aToAdd); } |
|
301 template <typename T> inline |
|
302 void RUniqueInstance<T>::TakeCopyL(const T* aToCopy) |
|
303 { iImpl.TakeCopyL(const_cast<T*>(aToCopy)); } |
|
304 template <typename T> inline |
|
305 const T* RUniqueInstance<T>::Peek() const |
|
306 { return reinterpret_cast<const T*>(iImpl.Peek()); } |
|
307 template <typename T> inline |
|
308 void RUniqueInstance<T>::CopyTo(RUniqueInstance<T>& aOther) const |
|
309 { iImpl.CopyTo(aOther.iImpl); } |
|
310 template <typename T> inline |
|
311 void RUniqueInstance<T>::MoveTo(RUniqueInstance<T>& aOther) |
|
312 { iImpl.MoveTo(aOther.iImpl); } |
|
313 template <typename T> inline |
|
314 T* RUniqueInstance<T>::DropL() |
|
315 { return reinterpret_cast<T*>(iImpl.DropL()); } |
|
316 template <typename T> inline |
|
317 void RUniqueInstance<T>::Close() |
|
318 { iImpl.Close(); } |
|
319 |
|
320 inline void RUniqueInstance<TDes>::TakeL(HBufC* aToAdd) |
|
321 { iImpl.TakeL(aToAdd); } |
|
322 inline void RUniqueInstance<TDes>::TakeCopyL(const TDesC* aToCopy) |
|
323 { iImpl.TakeCopyL(const_cast<TDesC*>(aToCopy)); } |
|
324 inline const TDesC* RUniqueInstance<TDes>::Peek() const |
|
325 { return reinterpret_cast<HBufC*>(iImpl.Peek()); } |
|
326 inline void RUniqueInstance<TDes>::CopyTo(RUniqueInstance<TDes>& aOther) const |
|
327 { iImpl.CopyTo(aOther.iImpl); } |
|
328 inline void RUniqueInstance<TDes>::MoveTo(RUniqueInstance<TDes>& aOther) |
|
329 { iImpl.MoveTo(aOther.iImpl); } |
|
330 inline HBufC* RUniqueInstance<TDes>::DropL() |
|
331 { return reinterpret_cast<HBufC*>(iImpl.DropL()); } |
|
332 inline void RUniqueInstance<TDes>::Close() |
|
333 { iImpl.Close(); } |
|
334 |
|
335 #endif // UNIQUEINSTANCE_H_ |