e8862cf4 |
1 | // Copyright (c) 2014 OPEN CASCADE SAS |
2 | // |
3 | // This file is part of Open CASCADE Technology software library. |
4 | // |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
10 | // |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
13 | |
14 | #include <QANCollection.hxx> |
15 | |
16 | #include <Draw.hxx> |
17 | #include <Draw_Interpretor.hxx> |
18 | |
19 | #include <Message_Status.hxx> |
20 | #include <NCollection_StdAllocator.hxx> |
21 | #include <NCollection_IncAllocator.hxx> |
22 | #include <NCollection_HeapAllocator.hxx> |
23 | #include <OSD_Timer.hxx> |
24 | #include <Standard_Assert.hxx> |
25 | #include <Standard_DefineHandle.hxx> |
26 | #include <Standard_Transient.hxx> |
27 | #include <TCollection_AsciiString.hxx> |
28 | #include <Geom_Line.hxx> |
29 | #include <Geom_BSplineCurve.hxx> |
30 | #include <Geom_Surface.hxx> |
31 | |
32 | #include <vector> |
33 | #include <memory> |
34 | #include <typeinfo> |
35 | |
e8862cf4 |
36 | // auxiliary macro to check and report status |
37 | #define CHECK(di,ok,what) di << "Checking " << what << (ok ? ": OK\n" : ": Error\n") |
38 | |
39 | //======================================================================= |
40 | //function : QAHandleOps |
41 | //purpose : Test Handle operations (mostly compile-time checks) |
42 | //======================================================================= |
43 | |
44 | // set of overloaded functions for checking resolution of arguments |
45 | inline void f (const Handle(Geom_Curve)&) {} |
46 | inline void func (const Handle(Geom_Curve)&) {} |
47 | inline void func (const Handle(Geom_BSplineCurve)&) {} |
48 | inline void func (const Handle(Geom_Surface)&) {} |
49 | inline void func (const Handle(gp_Pnt)&) {} |
50 | inline void func (const Handle(gp_XYZ)&) {} |
51 | inline void func (const Handle(gp_Trsf)&) {} |
52 | |
53 | inline void gunc (Handle(Geom_Curve)&) {} |
54 | |
55 | static Standard_Integer QAHandleOps (Draw_Interpretor& theDI, |
56 | Standard_Integer /*theArgNb*/, |
57 | const char** /*theArgVec*/) |
58 | { |
59 | // =============================================================== |
60 | // Part 1: classes inheriting transient |
61 | // =============================================================== |
62 | |
63 | Handle(Geom_Line) aLine = new Geom_Line (gp::Origin(), gp::DZ()); |
64 | CHECK(theDI, ! aLine.IsNull(), "handle for non-null"); |
65 | |
66 | const Handle(Geom_Line)& cLine = aLine; // cast to self const ref |
67 | const Handle(Geom_Curve)& cCurve = aLine; // cast to base const ref |
68 | Geom_Line* pLine = aLine.get(); |
69 | const Geom_Line* cpLine = aLine.get(); |
70 | Geom_Line& rLine = *aLine; |
71 | const Geom_Line& crLine = *cLine; |
72 | Handle(Geom_Curve) aCurve = aLine; // copy from handle to derived type |
73 | aCurve = cLine; // assignment to handle of derived type |
74 | Handle(Geom_Line) dLine (cpLine); // copy from handle to derived type |
75 | |
76 | aLine = Handle(Geom_Line)::DownCast (cCurve); |
77 | CHECK(theDI, ! aLine.IsNull(), "down cast"); |
78 | |
79 | // comparison operators |
80 | CHECK(theDI, aLine == aLine, "equality of handle to itself"); |
81 | CHECK(theDI, cLine == cLine, "equality of const handle to itself"); |
82 | CHECK(theDI, aLine == cLine, "equality of const and non-const handle"); |
83 | CHECK(theDI, aLine == cCurve, "equality of handle and base handle"); |
84 | CHECK(theDI, aLine == pLine, "equality of handle and pointer"); |
85 | CHECK(theDI, pLine == aLine, "equality of pointer and handle"); |
86 | CHECK(theDI, aLine == cpLine, "equality of handle and const pointer"); |
87 | CHECK(theDI, cpLine == aLine, "equality of const pointer and handle"); |
88 | CHECK(theDI, &rLine == aLine, "equality of reference and handle"); |
89 | CHECK(theDI, &crLine == aLine, "equality of reference and handle"); |
d1a67b9d |
90 | CHECK(theDI, aLine, "cast to bool"); |
e8862cf4 |
91 | |
92 | Handle(Geom_Line) aLin2; |
93 | CHECK(theDI, aLine != aLin2, "inequality of handle to the same type handle"); |
94 | CHECK(theDI, aLin2 != cLine, "inequality of const and non-const handle"); |
95 | CHECK(theDI, aLin2 != cCurve, "inequality of handle and base handle"); |
96 | CHECK(theDI, aLin2 != pLine, "inequality of handle and pointer"); |
97 | CHECK(theDI, pLine != aLin2, "inequality of pointer and handle"); |
98 | CHECK(theDI, aLin2 != cpLine, "inequality of handle and const pointer"); |
99 | CHECK(theDI, cpLine != aLin2, "inequality of const pointer and handle"); |
100 | |
101 | Handle(Geom_Curve) aCur2; |
102 | CHECK(theDI, aLine != aCur2, "inequality of handles of different types"); |
103 | CHECK(theDI, aCur2 != cLine, "inequality of const and non-const handle"); |
104 | CHECK(theDI, aCur2 != cCurve, "inequality of handle and base handle"); |
105 | CHECK(theDI, aCur2 != pLine, "inequality of handle and pointer"); |
106 | CHECK(theDI, pLine != aCur2, "inequality of pointer and handle"); |
107 | CHECK(theDI, aCur2 != cpLine, "inequality of handle and const pointer"); |
108 | CHECK(theDI, cpLine != aCur2, "inequality of const pointer and handle"); |
109 | |
110 | // passing handle as reference to base class |
111 | f (aLine); |
112 | |
113 | // passing handle to overloaded function accepting handle to another type |
114 | // will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads |
115 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3) |
116 | func (aLine); |
117 | func (cLine); |
118 | #endif |
119 | |
120 | // passing handle as non-const reference to base type |
121 | // currently allowed for compatibility |
122 | gunc (aLine); |
123 | Handle(Geom_Curve)& aCurve2 = aLine; // cast to base non-const ref |
e8862cf4 |
124 | |
125 | Handle(Geom_Line) qLine = cpLine; // constructor from const pointer -- could be made explicit... |
126 | |
d1a67b9d |
127 | // check whether compiler will destroy reference to temporary handle |
51740958 |
128 | const Handle(Geom_Curve)& aTmpRef (Handle(Geom_Line)::DownCast (aCurve2)); |
d1a67b9d |
129 | CHECK(theDI, ! aTmpRef.IsNull(), "local reference of handle to base type to temporary handle object"); |
130 | |
e8862cf4 |
131 | Handle(Geom_Surface) aSurf; |
132 | (void)aSurf; |
133 | |
134 | #if 0 |
135 | // each test in this section must cause compiler error |
136 | gunc (cLine); // passing const handle as non-const reference to base type |
137 | pLine = cLine.get(); // getting non-const pointer to contained object from const handle |
138 | Handle(Geom_Line) xLine = cCurve; // copy from handle to base type |
139 | Handle(Geom_BSplineCurve) aBSpl (new Geom_Line (gp::Origin(), gp::DX())); // construction from pointer to incompatible type |
140 | |
141 | CHECK(theDI, aLine == aSurf, "equality of handles of incompatible types"); |
142 | CHECK(theDI, aSurf == cLine, "equality of const and non-const handle"); |
143 | CHECK(theDI, aSurf == cCurve, "equality of handle and base handle"); |
144 | CHECK(theDI, aSurf == pLine, "equality of handle and pointer"); |
145 | CHECK(theDI, pLine == aSurf, "equality of pointer and handle"); |
146 | CHECK(theDI, aSurf == cpLine, "equality of handle and const pointer"); |
147 | CHECK(theDI, cpLine != aSurf, "equality of const pointer and handle"); |
148 | |
149 | CHECK(theDI, aLine != aSurf, "inequality of handles of incompatible types"); |
150 | CHECK(theDI, aSurf != cLine, "inequality of const and non-const handle"); |
151 | CHECK(theDI, aSurf != cCurve, "inequality of handle and base handle"); |
152 | CHECK(theDI, aSurf != pLine, "inequality of handle and pointer"); |
153 | CHECK(theDI, pLine != aSurf, "inequality of pointer and handle"); |
154 | CHECK(theDI, aSurf != cpLine, "inequality of handle and const pointer"); |
155 | CHECK(theDI, cpLine != aSurf, "inequality of const pointer and handle"); |
156 | #endif |
157 | |
158 | // =============================================================== |
159 | // Part 2: classes not inheriting transient |
160 | // =============================================================== |
161 | /* |
162 | Handle(gp_Pnt) aPnt = new gp_Pnt (gp::Origin()); |
163 | CHECK(theDI, ! aPnt.IsNull(), "handle for non-null"); |
164 | |
165 | const Handle(gp_Pnt)& cPnt = aPnt; // cast to self const ref |
166 | // const Handle(gp_XYZ)& cXYZ = aPnt; // cast to base const ref |
167 | gp_Pnt* pPnt = aPnt.get(); |
168 | const gp_Pnt* cpPnt = aPnt.get(); |
169 | gp_Pnt& rPnt = *aPnt; |
170 | const gp_Pnt& crPnt = *cPnt; |
171 | // Handle(gp_XYZ) aXYZ = aPnt; // copy from handle to derived type |
172 | // aXYZ = cPnt; // assignment to handle of derived type |
173 | |
174 | // aPnt = Handle(gp_Pnt)::DownCast (cXYZ); |
175 | // CHECK(theDI, ! aPnt.IsNull(), "down cast"); |
176 | |
177 | // comparison operators |
178 | CHECK(theDI, aPnt == aPnt, "equality of handle to itself"); |
179 | CHECK(theDI, cPnt == cPnt, "equality of const handle to itself"); |
180 | CHECK(theDI, aPnt == cPnt, "equality of const and non-const handle"); |
181 | // CHECK(theDI, aPnt == cXYZ, "equality of handle and base handle"); |
182 | CHECK(theDI, aPnt == pPnt, "equality of handle and pointer"); |
183 | CHECK(theDI, pPnt == aPnt, "equality of pointer and handle"); |
184 | CHECK(theDI, aPnt == cpPnt, "equality of handle and const pointer"); |
185 | CHECK(theDI, cpPnt == aPnt, "equality of const pointer and handle"); |
186 | CHECK(theDI, &rPnt == aPnt, "equality of reference and handle"); |
187 | CHECK(theDI, &crPnt == aPnt, "equality of reference and handle"); |
188 | |
189 | Handle(gp_Pnt) aPnt2; |
190 | CHECK(theDI, aPnt != aPnt2, "inequality of handle to the same type handle"); |
191 | CHECK(theDI, aPnt2 != cPnt, "inequality of const and non-const handle"); |
192 | // CHECK(theDI, aPnt2 != cXYZ, "inequality of handle and base handle"); |
193 | CHECK(theDI, aPnt2 != pPnt, "inequality of handle and pointer"); |
194 | CHECK(theDI, pPnt != aPnt2, "inequality of pointer and handle"); |
195 | CHECK(theDI, aPnt2 != cpPnt, "inequality of handle and const pointer"); |
196 | CHECK(theDI, cpPnt != aPnt2, "inequality of const pointer and handle"); |
197 | |
198 | Handle(gp_XYZ) aXYZ2; |
199 | CHECK(theDI, aLine != aPnt2, "inequality of handles of different types"); |
200 | CHECK(theDI, aXYZ2 != cPnt, "inequality of const and non-const handle"); |
201 | // CHECK(theDI, aXYZ2 != cXYZ, "inequality of handle and base handle"); |
202 | // CHECK(theDI, aXYZ2 != pPnt, "inequality of handle and pointer"); |
203 | // CHECK(theDI, pPnt != aXYZ2, "inequality of pointer and handle"); |
204 | // CHECK(theDI, aXYZ2 != cpPnt, "inequality of handle and const pointer"); |
205 | // CHECK(theDI, cpPnt != aXYZ2, "inequality of const pointer and handle"); |
206 | |
207 | // passing handle as reference to base class |
208 | func (aPnt); |
209 | func (cPnt); |
210 | */ |
211 | return 0; |
212 | } |
213 | |
214 | //======================================================================= |
215 | //function : QAHandleBool |
216 | //purpose : Test Handle -> bool conversion |
217 | //======================================================================= |
218 | static Standard_Integer QAHandleBool (Draw_Interpretor& theDI, |
219 | Standard_Integer /*theArgNb*/, |
220 | const char** /*theArgVec*/) |
221 | { |
222 | Handle(NCollection_BaseAllocator) aPtr = new NCollection_IncAllocator(); |
223 | |
224 | Handle(NCollection_IncAllocator) anInc = Handle(NCollection_IncAllocator)::DownCast (aPtr); |
225 | CHECK (theDI, ! anInc.IsNull(), "cast to NCollection_IncAllocator"); |
226 | |
227 | Handle(NCollection_BaseAllocator) anAlloc = Handle(NCollection_BaseAllocator)::DownCast (aPtr); |
228 | CHECK (theDI, ! anAlloc.IsNull(), "cast to NCollection_BaseAllocator"); |
229 | |
230 | Handle(NCollection_HeapAllocator) aHAlloc = Handle(NCollection_HeapAllocator)::DownCast (aPtr); |
231 | CHECK (theDI, aHAlloc.IsNull(), "cast to NCollection_HeapAllocator"); |
232 | |
233 | return 0; |
234 | } |
235 | |
236 | // Auxiliary macros to create hierarchy of 50 classes |
237 | #define QA_DEFINECLASS(theClass, theParent) \ |
238 | class theClass : public theParent \ |
239 | { \ |
240 | public:\ |
241 | theClass() {}; \ |
242 | virtual ~theClass() {}; \ |
243 | virtual const char* Name() const { return #theClass; } \ |
244 | virtual Standard_Transient* CreateParent() const { return new theParent(); } \ |
245 | virtual Standard_Transient* Clone() const { return new theClass(); } \ |
246 | DEFINE_STANDARD_RTTI(theClass, theParent); \ |
247 | };\ |
248 | DEFINE_STANDARD_HANDLE (theClass, theParent) \ |
249 | IMPLEMENT_STANDARD_HANDLE (theClass, theParent) \ |
250 | IMPLEMENT_STANDARD_RTTIEXT(theClass, theParent) |
251 | |
252 | #define QA_NAME(theNum) qaclass ## theNum ## _ ## 50 |
253 | #define QA_HANDLE_NAME(theNum) Handle(qaclass ## theNum ## _ ## 50) |
254 | |
255 | #define QA_DEFINECLASS10(theParent, theTens) \ |
256 | QA_DEFINECLASS(QA_NAME(theTens ## 0), theParent) \ |
257 | QA_DEFINECLASS(QA_NAME(theTens ## 1), QA_NAME(theTens ## 0)) \ |
258 | QA_DEFINECLASS(QA_NAME(theTens ## 2), QA_NAME(theTens ## 1)) \ |
259 | QA_DEFINECLASS(QA_NAME(theTens ## 3), QA_NAME(theTens ## 2)) \ |
260 | QA_DEFINECLASS(QA_NAME(theTens ## 4), QA_NAME(theTens ## 3)) \ |
261 | QA_DEFINECLASS(QA_NAME(theTens ## 5), QA_NAME(theTens ## 4)) \ |
262 | QA_DEFINECLASS(QA_NAME(theTens ## 6), QA_NAME(theTens ## 5)) \ |
263 | QA_DEFINECLASS(QA_NAME(theTens ## 7), QA_NAME(theTens ## 6)) \ |
264 | QA_DEFINECLASS(QA_NAME(theTens ## 8), QA_NAME(theTens ## 7)) \ |
265 | QA_DEFINECLASS(QA_NAME(theTens ## 9), QA_NAME(theTens ## 8)) |
266 | |
267 | QA_DEFINECLASS10(Standard_Transient, 0) |
268 | QA_DEFINECLASS10(qaclass09_50, 1) |
269 | QA_DEFINECLASS10(qaclass19_50, 2) |
270 | QA_DEFINECLASS10(qaclass29_50, 3) |
271 | QA_DEFINECLASS10(qaclass39_50, 4) |
272 | QA_DEFINECLASS (qaclass50_50, qaclass49_50) |
273 | |
274 | namespace |
275 | { |
276 | class qaclass50_50ANON : public qaclass49_50 |
277 | { |
278 | public: |
279 | qaclass50_50ANON() {} |
280 | }; |
281 | } |
282 | |
283 | namespace QaNamespace |
284 | { |
285 | class qaclass50_50 : public qaclass49_50 |
286 | { |
287 | public: |
288 | qaclass50_50() {} |
289 | }; |
290 | } |
291 | |
292 | namespace { |
293 | //! Timer sentry. Prints elapsed time information at destruction time. |
294 | class QATimer : public OSD_Timer |
295 | { |
296 | public: |
297 | enum TimeFormat |
298 | { |
299 | Seconds, |
300 | Milliseconds, |
301 | Microseconds, |
302 | Nanoseconds, |
303 | s = Seconds, |
304 | ms = Milliseconds, |
305 | ns = Nanoseconds, |
306 | }; |
307 | |
308 | public: |
309 | //! Main constructor - automatically starts the timer. |
310 | QATimer (Draw_Interpretor& theDI, |
311 | Standard_CString theTitle, |
312 | const TimeFormat theFormat, |
313 | const Standard_Integer theNbIters = 1, |
314 | const Standard_Boolean theToPrintFormat = Standard_False) |
315 | : myDI(&theDI), |
316 | myTitle (theTitle), |
317 | myFormat (theFormat), |
318 | myNbIters (theNbIters), |
319 | myToPrintFormat (theToPrintFormat) |
320 | { |
321 | Start(); |
322 | } |
323 | |
324 | //! Destructor - stops the timer and prints statistics. |
325 | ~QATimer() |
326 | { |
327 | Stop(); |
328 | if (myTitle != NULL) |
329 | { |
330 | (*myDI) << myTitle; |
331 | } |
332 | switch (myFormat) |
333 | { |
334 | case Seconds: |
335 | (*myDI) << ElapsedTime() / Standard_Real(myNbIters); |
336 | if (myToPrintFormat) |
337 | { |
338 | (*myDI) << " s"; |
339 | } |
340 | break; |
341 | case Milliseconds: |
342 | (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0; |
343 | if (myToPrintFormat) |
344 | { |
345 | (*myDI) << " ms"; |
346 | } |
347 | break; |
348 | case Microseconds: |
349 | (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0; |
350 | if (myToPrintFormat) |
351 | { |
352 | (*myDI) << " microseconds"; |
353 | } |
354 | break; |
355 | case Nanoseconds: |
356 | (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0; |
357 | if (myToPrintFormat) |
358 | { |
359 | (*myDI) << " ns"; |
360 | } |
361 | break; |
362 | } |
363 | } |
364 | |
365 | private: |
366 | Draw_Interpretor* myDI; |
367 | Standard_CString myTitle; //!< timer description |
368 | TimeFormat myFormat; //!< time format |
369 | Standard_Integer myNbIters; //!< iterations number |
370 | Standard_Boolean myToPrintFormat; //!< add time format |
371 | }; |
372 | } // anonymous namespace |
373 | |
374 | //======================================================================= |
375 | //function : QAHandleInc |
376 | //purpose : Estimate the smart-pointer counter incrementing time |
377 | //======================================================================= |
378 | static Standard_Integer QAHandleInc (Draw_Interpretor& theDI, |
379 | Standard_Integer theArgNb, |
380 | const char** theArgVec) |
381 | { |
382 | if (theArgNb > 2) |
383 | { |
384 | std::cout << "Error: wrong syntax! See usage:\n"; |
385 | theDI.PrintHelp (theArgVec[0]); |
386 | return 1; |
387 | } |
388 | const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi (theArgVec[1]) : 10000000; |
389 | if (aNbIters < 1) |
390 | { |
391 | std::cout << "Error: number of iterations should be positive!\n"; |
392 | return 1; |
393 | } |
394 | |
395 | Handle(Standard_Transient) aHandle = new Standard_Transient(); |
5b111128 |
396 | std::shared_ptr<Standard_Transient> aSharePtr (new Standard_Transient()); |
e8862cf4 |
397 | theDI << "Time of creating and destroying " << aNbIters << " smart pointers to the same object, per item, ns:"; |
398 | { |
399 | { |
400 | QATimer aTimer (theDI, "\nOCCT Handle: ", QATimer::ns, aNbIters); |
401 | { |
402 | std::vector<Handle(Standard_Transient)> aHandles (aNbIters); |
403 | for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter) |
404 | { |
405 | aHandles[anIter] = aHandle; |
406 | } |
407 | } |
408 | } |
409 | { |
410 | QATimer aTimer (theDI, "\nsC++ shared_ptr: ", QATimer::ns, aNbIters); |
411 | { |
5b111128 |
412 | std::vector< std::shared_ptr<Standard_Transient> > aSharePointers (aNbIters); |
e8862cf4 |
413 | for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter) |
414 | { |
415 | aSharePointers[anIter] = aSharePtr; |
416 | } |
417 | } |
418 | } |
419 | } |
420 | return 0; |
421 | } |
422 | |
423 | namespace |
424 | { |
425 | //! Auxiliary class to perform casting to specified type. |
426 | template<typename TTo> struct QACast |
427 | { |
428 | //! Perform casting using OCCT DownCast() operation. |
429 | template<typename TFrom> |
430 | static void doDownCast (Draw_Interpretor& theDI, |
431 | const Standard_Integer theNbIters, |
432 | const TFrom& theHandle) |
433 | { |
434 | std::vector<TTo> aHandles (theNbIters); |
435 | { |
436 | QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); |
437 | for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) |
438 | { |
439 | aHandles[anIter] = TTo::DownCast (theHandle); |
440 | } |
441 | } |
442 | } |
443 | |
444 | //! Perform casting using standard C++ dynamic_cast<> operation. |
445 | template<typename TFrom> |
446 | static void doDynamicCast (Draw_Interpretor& theDI, |
447 | const Standard_Integer theNbIters, |
448 | const TFrom& theHandle) |
449 | { |
450 | std::vector<typename TTo::element_type*> aPointers (theNbIters); |
451 | { |
452 | QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); |
453 | for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) |
454 | { |
455 | aPointers[anIter] = dynamic_cast<typename TTo::element_type* > (theHandle.operator->()); |
456 | } |
457 | } |
458 | } |
459 | |
460 | //! Perform dynamic casting using shared_ptr::dynamic_pointer_cast operation. |
461 | template<typename TFrom> |
462 | static void doShareCast (Draw_Interpretor& theDI, |
463 | const Standard_Integer theNbIters, |
5b111128 |
464 | const std::shared_ptr<TFrom>& theSharePtr) |
e8862cf4 |
465 | { |
5b111128 |
466 | std::vector< std::shared_ptr<typename TTo::element_type> > aSharePointers (theNbIters); |
e8862cf4 |
467 | { |
468 | QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); |
469 | for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) |
470 | { |
5b111128 |
471 | aSharePointers[anIter] = std::dynamic_pointer_cast<typename TTo::element_type, TFrom> (theSharePtr); |
e8862cf4 |
472 | } |
473 | } |
474 | } |
475 | |
476 | }; |
477 | |
478 | template<typename TAs> |
479 | static void qaCastAs (Draw_Interpretor& theDI, |
480 | const qaclass00_50& theInst, |
481 | const Standard_Integer theNbIters) |
482 | { |
483 | #define QA_TEST_CAST10(theTens, theDoCast) \ |
484 | QACast<QA_HANDLE_NAME(theTens ## 0)>::theDoCast(theDI, theNbIters, aPtr); \ |
1c29294e |
485 | QACast<QA_HANDLE_NAME(theTens ## 5)>::theDoCast(theDI, theNbIters, aPtr); |
486 | |
e8862cf4 |
487 | typedef typename TAs::element_type aPtrType; |
488 | TAs aDummy (new aPtrType()); |
489 | theDI << "Making a pointer:\n"; |
490 | theDI << aDummy->DynamicType()->Name() << "* ptr = new " << theInst.DynamicType()->Name() << "\n"; |
491 | theDI << "then measuring the time of casting it to base classes from qaclass00_50 to qaclass50_50, ns\n"; |
492 | if (!theInst.IsKind (aDummy->DynamicType())) |
493 | { |
494 | return; |
495 | } |
496 | |
497 | theDI << "\nOCCT Handle: "; |
498 | { |
499 | TAs aPtr ((typename TAs::element_type* )theInst.Clone()); |
500 | QA_TEST_CAST10(0, doDownCast); |
501 | QA_TEST_CAST10(1, doDownCast); |
502 | QA_TEST_CAST10(2, doDownCast); |
503 | QA_TEST_CAST10(3, doDownCast); |
504 | QA_TEST_CAST10(4, doDownCast); |
505 | QACast<Handle(qaclass50_50)>::doDownCast(theDI, theNbIters, aPtr); |
506 | } |
507 | theDI << "\nC++ dynamic_cast: "; |
508 | { |
509 | TAs aPtr ((typename TAs::element_type* )theInst.Clone()); |
510 | QA_TEST_CAST10(0, doDynamicCast); |
511 | QA_TEST_CAST10(1, doDynamicCast); |
512 | QA_TEST_CAST10(2, doDynamicCast); |
513 | QA_TEST_CAST10(3, doDynamicCast); |
514 | QA_TEST_CAST10(4, doDynamicCast); |
515 | QACast<Handle(qaclass50_50)>::doDynamicCast(theDI, theNbIters, aPtr); |
516 | } |
517 | theDI << "\nC++ dynamic_pointer_cast: "; |
518 | { |
5b111128 |
519 | std::shared_ptr<typename TAs::element_type> aPtr ((typename TAs::element_type* )theInst.Clone()); |
e8862cf4 |
520 | QA_TEST_CAST10(0, doShareCast); |
521 | QA_TEST_CAST10(1, doShareCast); |
522 | QA_TEST_CAST10(2, doShareCast); |
523 | QA_TEST_CAST10(3, doShareCast); |
524 | QA_TEST_CAST10(4, doShareCast); |
525 | QACast<Handle(qaclass50_50)>::doShareCast(theDI, theNbIters, aPtr); |
526 | } |
527 | } |
528 | |
529 | } |
530 | |
531 | //======================================================================= |
532 | //function : QAHandleCast |
533 | //purpose : Estimate performance of RTTI mechanisms - dynamic type casting |
534 | //======================================================================= |
535 | static Standard_Integer QAHandleCast (Draw_Interpretor& theDI, |
536 | Standard_Integer theArgNb, |
537 | const char** theArgVec) |
538 | { |
539 | if (theArgNb > 4) |
540 | { |
541 | std::cout << "Error: wrong syntax! See usage:\n"; |
542 | theDI.PrintHelp (theArgVec[0]); |
543 | return 1; |
544 | } |
545 | Standard_Integer anArgIter = 0; |
546 | const Standard_Integer anInst = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 50; |
547 | const Standard_Integer aPtrTo = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 0; |
548 | const Standard_Integer aNbIters = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 1000000; |
549 | |
550 | if (aNbIters < 1) |
551 | { |
552 | std::cout << "Error: number of iterations (" << aNbIters << ") should be positive!\n"; |
553 | return 1; |
554 | } |
555 | if (anInst > 50 || anInst < 0) |
556 | { |
557 | std::cout << "Error: class instance (" << anInst << ") should be specified within 0..50 range!\n"; |
558 | return 1; |
559 | } |
560 | if (aPtrTo > anInst || aPtrTo < 0) |
561 | { |
562 | std::cout << "Error: class pointer (" << aPtrTo << ") should be specified within 0.." << anInst << " range!\n"; |
563 | return 1; |
564 | } |
565 | else if (aPtrTo % 10 != 0) |
566 | { |
567 | std::cout << "Error: class pointer (" << aPtrTo << ") should be multiple of 10!\n"; |
568 | return 1; |
569 | } |
570 | |
571 | Handle(qaclass00_50) aHandle = new qaclass50_50(); |
572 | for (Standard_Integer anInstIter = 50 - anInst; anInstIter > 0; --anInstIter) |
573 | { |
574 | Handle(Standard_Transient) aParent (aHandle->CreateParent()); |
575 | aHandle = Handle(qaclass00_50)::DownCast (aParent); |
576 | } |
577 | |
578 | std::ios::fmtflags aFlags = std::cout.flags(); |
579 | std::cout.precision (5); |
580 | |
e8862cf4 |
581 | switch (aPtrTo) |
582 | { |
583 | // vc11 requires /bigobj option |
e8862cf4 |
584 | case 0: qaCastAs<Handle(qaclass00_50)>(theDI, *aHandle, aNbIters); break; |
585 | case 10: qaCastAs<Handle(qaclass10_50)>(theDI, *aHandle, aNbIters); break; |
586 | case 20: qaCastAs<Handle(qaclass20_50)>(theDI, *aHandle, aNbIters); break; |
587 | case 30: qaCastAs<Handle(qaclass30_50)>(theDI, *aHandle, aNbIters); break; |
588 | case 40: qaCastAs<Handle(qaclass40_50)>(theDI, *aHandle, aNbIters); break; |
589 | case 50: qaCastAs<Handle(qaclass50_50)>(theDI, *aHandle, aNbIters); break; |
590 | } |
591 | std::cout.setf (aFlags); |
592 | return 0; |
593 | } |
594 | |
595 | //======================================================================= |
596 | //function : QAHandleKind |
597 | //purpose : |
598 | //======================================================================= |
599 | static Standard_Integer QAHandleKind (Draw_Interpretor& /*theDI*/, |
600 | Standard_Integer /*theArgNb*/, |
601 | const char** /*theArgVec*/) |
602 | { |
603 | Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50); |
604 | Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50); |
605 | Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50); |
606 | Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50); |
607 | Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50); |
608 | Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50); |
609 | |
610 | Handle(qaclass00_50) aHandle = new qaclass40_50(); |
611 | |
612 | #define QA_CHECK(theDesc, theExpr, theValue) \ |
613 | {\ |
614 | const bool isTrue = !!(theExpr); \ |
615 | std::cout << theDesc << (isTrue ? " TRUE " : " FALSE ") << (isTrue == theValue ? " is OK\n" : " is Error\n"); \ |
616 | } |
617 | |
618 | std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n"; |
619 | for (Handle(Standard_Type) aType = aHandle->DynamicType(); ! aType.IsNull(); aType = aType->Parent()) |
620 | { |
621 | std::cout << " - " << aType->Name() << "\n"; |
622 | } |
623 | |
624 | QA_CHECK ("Name == qaclass40_50 : ", TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(), true); |
625 | |
626 | QA_CHECK ("IsKind (aType00) : ", aHandle->IsKind (aType00), true); |
627 | QA_CHECK ("IsKind (aType10) : ", aHandle->IsKind (aType10), true); |
628 | QA_CHECK ("IsKind (aType20) : ", aHandle->IsKind (aType20), true); |
629 | QA_CHECK ("IsKind (aType30) : ", aHandle->IsKind (aType30), true); |
630 | QA_CHECK ("IsKind (aType40) : ", aHandle->IsKind (aType40), true); |
631 | QA_CHECK ("IsKind (aType50) : ", aHandle->IsKind (aType50), false); |
632 | |
633 | QA_CHECK ("IsKind (\"qaclass00_50\"): ", aHandle->IsKind ("qaclass00_50"), true); |
634 | QA_CHECK ("IsKind (\"qaclass10_50\"): ", aHandle->IsKind ("qaclass10_50"), true); |
635 | QA_CHECK ("IsKind (\"qaclass20_50\"): ", aHandle->IsKind ("qaclass20_50"), true); |
636 | QA_CHECK ("IsKind (\"qaclass30_50\"): ", aHandle->IsKind ("qaclass30_50"), true); |
637 | QA_CHECK ("IsKind (\"qaclass40_50\"): ", aHandle->IsKind ("qaclass40_50"), true); |
638 | QA_CHECK ("IsKind (\"qaclass50_50\"): ", aHandle->IsKind ("qaclass50_50"), false); |
639 | |
640 | QA_CHECK ("IsInstance (aType00) : ", aHandle->IsInstance (aType00), false); |
641 | QA_CHECK ("IsInstance (aType10) : ", aHandle->IsInstance (aType10), false); |
642 | QA_CHECK ("IsInstance (aType20) : ", aHandle->IsInstance (aType20), false); |
643 | QA_CHECK ("IsInstance (aType30) : ", aHandle->IsInstance (aType30), false); |
644 | QA_CHECK ("IsInstance (aType40) : ", aHandle->IsInstance (aType40), true); |
645 | QA_CHECK ("IsInstance (aType50) : ", aHandle->IsInstance (aType50), false); |
646 | |
647 | #ifdef HAVE_CPP11 |
648 | std::cout << "\nC++11:\n"; |
649 | std::type_index aCppType = typeid(*aHandle.operator->()); |
650 | std::cout << "typeid().name() = '" << typeid(*aHandle.operator->()).name() << "'\n"; |
651 | #ifdef _MSC_VER |
652 | std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n"; |
653 | #endif |
654 | |
655 | std::cout << "[ANON]typeid().name() = '" << typeid(qaclass50_50ANON).name() << "'\n"; |
656 | #ifdef _MSC_VER |
657 | std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n"; |
658 | #endif |
659 | |
660 | std::cout << "[NS]typeid().name() = '" << typeid(QaNamespace::qaclass50_50).name() << "'\n"; |
661 | #ifdef _MSC_VER |
662 | std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name() << "'\n"; |
663 | #endif |
664 | |
665 | QA_CHECK ("is typeid (aType00) : ", typeid(*aHandle.operator->()) == typeid(qaclass00_50), false); |
666 | QA_CHECK ("is typeid (aType10) : ", typeid(*aHandle.operator->()) == typeid(qaclass10_50), false); |
667 | QA_CHECK ("is typeid (aType20) : ", typeid(*aHandle.operator->()) == typeid(qaclass20_50), false); |
668 | QA_CHECK ("is typeid (aType30) : ", typeid(*aHandle.operator->()) == typeid(qaclass30_50), false); |
669 | QA_CHECK ("is typeid (aType40) : ", typeid(*aHandle.operator->()) == typeid(qaclass40_50), true); |
670 | QA_CHECK ("is typeid (aType50) : ", typeid(*aHandle.operator->()) == typeid(qaclass50_50), false); |
671 | |
672 | QA_CHECK ("is type_index (aType00) : ", aCppType == typeid(qaclass00_50), false); |
673 | QA_CHECK ("is type_index (aType40) : ", aCppType == typeid(qaclass40_50), true); |
674 | |
675 | QA_CHECK ("IsClass(Standard_Transient): ", std::is_class<Standard_Transient>::value == !!STANDARD_TYPE(Standard_Transient)->IsClass(), true); |
676 | //QA_CHECK ("IsEnum (Message_Status) : ", std::is_enum<Message_Status>::value == !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true); |
677 | #endif |
678 | |
679 | return 0; |
680 | } |
681 | |
682 | void QANCollection::CommandsHandle (Draw_Interpretor& theCommands) |
683 | { |
684 | const char* THE_GROUP = "QANCollection"; |
685 | theCommands.Add ("QAHandleBool", |
686 | "Test handle boolean operator", |
687 | __FILE__, QAHandleBool, THE_GROUP); |
688 | theCommands.Add ("QAHandleInc", |
689 | "QAHandleInc nbIter=1000000" |
690 | "\n\t\t: Test handle increment performance", |
691 | __FILE__, QAHandleInc, THE_GROUP); |
692 | theCommands.Add ("QAHandleCast", |
693 | "QAHandleCast [instance=50 [pointerTo=0 [nbIter=1000000]]]" |
694 | "\n\t\t: Test handle DownCast performance." |
695 | "\n\t\t: instance - specifies the depth of instantiated class" |
696 | "\n\t\t: pointerTo - specifies the depth of pointer class, where instance is stored into", |
697 | __FILE__, QAHandleCast, THE_GROUP); |
698 | theCommands.Add ("QAHandleKind", |
699 | "Test handle IsKind", |
700 | __FILE__, QAHandleKind, THE_GROUP); |
701 | theCommands.Add ("QAHandleOps", |
702 | "Test handle operations", |
703 | __FILE__, QAHandleOps, THE_GROUP); |
704 | return; |
705 | } |