|
1 // dobject.h |
|
2 // |
|
3 // Copyright (c) 1998 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "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 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 /** |
|
14 @file |
|
15 @internalTechnology |
|
16 */ |
|
17 |
|
18 #ifndef __DOBJECT_H__ |
|
19 #define __DOBJECT_H__ |
|
20 |
|
21 #ifdef _DEBUG |
|
22 // In DEBUG builds use linear growth by 1 to aid kernel heap checking |
|
23 #else |
|
24 const TInt KObjectConMinSize=8; |
|
25 #endif |
|
26 const TInt KObjectIxGranularity=8; |
|
27 const TInt KObjectIndexMask=0x7fff; |
|
28 const TInt KObjectMaxIndex=0x7fff; |
|
29 const TInt KObjectInstanceShift=16; |
|
30 const TInt KObjectInstanceMask=0x3fff; |
|
31 const TInt KObjectIxMaxHandles=0x8000; |
|
32 |
|
33 inline TInt index(TInt aHandle) |
|
34 {return(aHandle&KObjectIndexMask);} |
|
35 inline TInt instance(TInt aHandle) |
|
36 {return((aHandle>>KObjectInstanceShift)&KObjectInstanceMask);} |
|
37 inline TInt instanceLimit(TInt& aCount) |
|
38 {return ((aCount&KObjectInstanceMask)==0) ? ((++aCount)&KObjectInstanceMask) : aCount&KObjectInstanceMask;} |
|
39 inline TInt makeHandle(TInt aIndex, TInt aInstance) |
|
40 {return((TInt)((aInstance<<KObjectInstanceShift)|aIndex));} |
|
41 |
|
42 enum TDObjectPanic |
|
43 { |
|
44 EObjObjectStillReferenced, |
|
45 EObjNegativeAccessCount, |
|
46 EObjRemoveObjectNotFound, |
|
47 EObjRemoveContainerNotFound, |
|
48 EObjRemoveBadHandle, |
|
49 EObjFindBadHandle, |
|
50 EObjFindIndexOutOfRange, |
|
51 EDObjectConDestroyed, |
|
52 EArrayIndexOutOfRange, |
|
53 EObjInconsistent, |
|
54 }; |
|
55 |
|
56 inline void Panic(TDObjectPanic aPanic) |
|
57 { Kern::Fault("DOBJECT",aPanic); } |
|
58 |
|
59 |
|
60 //BEGIN TOMSCI |
|
61 // This is needed because on 9.1 the DObjectIx header is defined as IMPORT_C |
|
62 #undef IMPORT_C |
|
63 #define IMPORT_C |
|
64 #define DObjectIx DObjectIxNinePointTwoHack // So that we're not redefining DObjectIx |
|
65 |
|
66 NONSHARABLE_CLASS(DObjectIx) : public DBase |
|
67 { |
|
68 public: |
|
69 enum {ENoClose=KHandleNoClose,ELocalHandle=0x40000000}; |
|
70 public: |
|
71 IMPORT_C static DObjectIx* New(TAny* aPtr); |
|
72 IMPORT_C ~DObjectIx(); |
|
73 IMPORT_C TInt Add(DObject* aObj, TInt& aHandle); |
|
74 IMPORT_C TInt Remove(TInt aHandle, DObject*& aObject, TAny*& aPtr); |
|
75 IMPORT_C DObject* At(TInt aHandle,TInt aUniqueID); |
|
76 IMPORT_C DObject* At(TInt aHandle); |
|
77 IMPORT_C TInt At(DObject* aObject); |
|
78 IMPORT_C TInt Count(DObject* aObject); |
|
79 IMPORT_C DObject* operator[](TInt aIndex); |
|
80 TInt LastHandle(); |
|
81 static void Wait(); |
|
82 static void Signal(); |
|
83 inline TInt Count(); |
|
84 inline TInt ActiveCount(); |
|
85 protected: |
|
86 IMPORT_C DObjectIx(TAny* aPtr); |
|
87 private: |
|
88 void UpdateState(); |
|
89 private: |
|
90 TInt iNextInstance; |
|
91 TInt iAllocated; // Max entries before realloc needed |
|
92 TInt iCount; // Points to at least 1 above the highest active index |
|
93 TInt iActiveCount; // Number of actual entries in the index |
|
94 SDObjectIxRec* iObjects; |
|
95 TAny* iPtr; |
|
96 TInt iFree; // The index of the first free slot or -1. |
|
97 TInt iUpdateDisabled; // If >0, disables: iCount update, reorder of the free list and memory shrinking. |
|
98 public: |
|
99 static DMutex* HandleMutex; |
|
100 public: |
|
101 friend void PreprocessHandler(); |
|
102 friend class DThread; |
|
103 friend class K; |
|
104 friend class Monitor; |
|
105 }; |
|
106 |
|
107 inline TInt DObjectIx::Count() |
|
108 {return iCount;} |
|
109 inline TInt DObjectIx::ActiveCount() |
|
110 {return iActiveCount;} |
|
111 |
|
112 #undef DObjectIx |
|
113 |
|
114 // |
|
115 // Include these in a header file |
|
116 // |
|
117 |
|
118 __ASSERT_COMPILE(sizeof(DObject) == 6*4 || sizeof(DObject) == 8*4); // We can't cope if the size changes again! |
|
119 #define DOBJECT_PADDING TUint64 _padding |
|
120 const TBool KCompiledUsingOldDefinition = sizeof(DObject) == 6*4; |
|
121 #define ADD_PADDING(type, variablePtr) (*reinterpret_cast<type*>((TUint8*)variablePtr + sizeof(TUint64))) |
|
122 #define SUBTRACT_PADDING(type, variablePtr) (*reinterpret_cast<type*>((TUint8*)variablePtr - sizeof(TUint64))) |
|
123 |
|
124 |
|
125 template <class T> |
|
126 class TemplatedPadder |
|
127 { |
|
128 public: |
|
129 inline static T& AddPadding(T* aPtr) |
|
130 { |
|
131 return ADD_PADDING(T, aPtr); |
|
132 } |
|
133 inline static T& SubtractPadding(T* aPtr) |
|
134 { |
|
135 return SUBTRACT_PADDING(T, aPtr); |
|
136 } |
|
137 }; |
|
138 |
|
139 template <class T> |
|
140 inline T& AddPadding(T* aPtr) |
|
141 { |
|
142 return TemplatedPadder<T>::AddPadding(aPtr); |
|
143 } |
|
144 |
|
145 template <class T> |
|
146 inline T& SubtractPadding(T* aPtr) |
|
147 { |
|
148 return TemplatedPadder<T>::SubtractPadding(aPtr); |
|
149 } |
|
150 |
|
151 TBool CalculateDObjectSize(); // returns false if unable to determine |
|
152 extern TBool gRunningWithOldDefinition; |
|
153 |
|
154 /* The SAFE_MEMBER macro exists because DObject grew by 64 bits between 9.1 and 9.2, therefore to write a |
|
155 * DObject-derived class (such as a DLogicalChannel in an LDD) that can be compiled on one but also works on the |
|
156 * other requires that you be very careful accessing member data of your DObject-derived objects, because the |
|
157 * offsets are different on the two OS releases. This macro abstracts the differences away by calculating when |
|
158 * an 8 byte correction needs to be applied to where the compiler thinks the variable is versus where the runtime |
|
159 * knows it is. By necessity, it has a weird definition, that relies on the above helper macros and also on |
|
160 * CalculateDObjectSize being called at some point before the first time any code using SAFE_MACRO is run. |
|
161 * It is recommended that for an LDD, you call it from within your DECLARE_EXTENSION_LDD before doing anything |
|
162 * else. |
|
163 * |
|
164 * SAFE_MEMBER can only be used to access member data of DObject-derived classes, and should be used in ALL |
|
165 * places where the instance variables are used or set, this includes instance variables of the superclass and |
|
166 * instance variables in DObject-derived objects you define yourself. Accesses to instance variables of DObject |
|
167 * itself must NOT use this macro, since the DObject variable offsets do not change. In order to make sure your |
|
168 * class is large enough and that the macro can be used consistantly, you must include a DOBJECT_PADDING at |
|
169 * the *end* of all of your DObject subclass definition. You won't get any warning if you forget to do this, |
|
170 * It will just crash. Likewise if you use SAFE_MEMBER to access the member data of the DObject itself. |
|
171 * |
|
172 * In other words: |
|
173 * DO use SAFE_MEMBER to access the member data of DMyClassThatIsDerivedFromDObject |
|
174 * DO use SAFE_MEMBER to access the member data of DLogicalChannel/DLogicalDevice/DThread etc |
|
175 * DON'T use it to access the member data of DObject itself |
|
176 * ALWAYS include a DOBJECT_PADDING at the end of your DMyDObjectDerivedClass - ie after any other member data |
|
177 * |
|
178 */ |
|
179 |
|
180 #define SAFE_MEMBER(variable) ( \ |
|
181 (KCompiledUsingOldDefinition && gRunningWithOldDefinition) ? variable : ( \ |
|
182 (KCompiledUsingOldDefinition && !gRunningWithOldDefinition) ? AddPadding(&variable) : ( \ |
|
183 (!KCompiledUsingOldDefinition && gRunningWithOldDefinition) ? SubtractPadding(&variable) : ( \ |
|
184 /* running and compiling with new-definition DObject */ variable )))) |
|
185 |
|
186 /* Old definition that doesn't require templating to work, (so is callable from non-C++). A consequence is you |
|
187 * have to explicitly give the type of the variable. |
|
188 */ |
|
189 //#define SAFE_MEMBER(type, variable) ( \ |
|
190 // (KCompiledUsingOldDefinition && gRunningWithOldDefinition) ? variable : ( \ |
|
191 // (KCompiledUsingOldDefinition && !gRunningWithOldDefinition) ? ADD_PADDING(type, &variable) : ( \ |
|
192 // (!KCompiledUsingOldDefinition && gRunningWithOldDefinition) ? SUBTRACT_PADDING(type, &variable) : ( \ |
|
193 // /* running and compiling with new-definition DObject */ variable )))) |
|
194 |
|
195 |
|
196 /* These macros are equivalent to _FOFF and _LOFF and should be used whenever |
|
197 * f refers to a member variable that you would need to use SAFE_MEMBER on |
|
198 */ |
|
199 #define _SAFE_FOFF(c,f) (((TInt)& SAFE_MEMBER((((c *)0x1000)->f) ) )-0x1000) |
|
200 #define _SAFE_LOFF(p,T,f) ((T*)(((TUint8*)(p))-_SAFE_FOFF(T,f))) |
|
201 |
|
202 //END TOMSCI |
|
203 |
|
204 #endif |