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 | |
79104795 |
236 | // Auxiliary class to define new virtual methods |
237 | class Transient_Root : public Standard_Transient |
238 | { |
239 | public: |
240 | virtual const char* Name() const { return "Transient_Root"; } |
241 | virtual Standard_Transient* CreateParent() const { return new Standard_Transient; } |
242 | virtual Standard_Transient* Clone() const { return new Transient_Root; } |
243 | DEFINE_STANDARD_RTTI(Transient_Root, Standard_Transient) |
244 | }; |
245 | DEFINE_STANDARD_HANDLE(Transient_Root, Standard_Transient) |
246 | |
e8862cf4 |
247 | // Auxiliary macros to create hierarchy of 50 classes |
248 | #define QA_DEFINECLASS(theClass, theParent) \ |
249 | class theClass : public theParent \ |
250 | { \ |
251 | public:\ |
79104795 |
252 | virtual const char* Name() const Standard_OVERRIDE { return #theClass; } \ |
253 | virtual Standard_Transient* CreateParent() const Standard_OVERRIDE { return new theParent(); } \ |
254 | virtual Standard_Transient* Clone() const Standard_OVERRIDE { return new theClass(); } \ |
255 | DEFINE_STANDARD_RTTI(theClass, theParent) \ |
e8862cf4 |
256 | };\ |
257 | DEFINE_STANDARD_HANDLE (theClass, theParent) \ |
258 | IMPLEMENT_STANDARD_HANDLE (theClass, theParent) \ |
259 | IMPLEMENT_STANDARD_RTTIEXT(theClass, theParent) |
260 | |
261 | #define QA_NAME(theNum) qaclass ## theNum ## _ ## 50 |
262 | #define QA_HANDLE_NAME(theNum) Handle(qaclass ## theNum ## _ ## 50) |
263 | |
264 | #define QA_DEFINECLASS10(theParent, theTens) \ |
265 | QA_DEFINECLASS(QA_NAME(theTens ## 0), theParent) \ |
266 | QA_DEFINECLASS(QA_NAME(theTens ## 1), QA_NAME(theTens ## 0)) \ |
267 | QA_DEFINECLASS(QA_NAME(theTens ## 2), QA_NAME(theTens ## 1)) \ |
268 | QA_DEFINECLASS(QA_NAME(theTens ## 3), QA_NAME(theTens ## 2)) \ |
269 | QA_DEFINECLASS(QA_NAME(theTens ## 4), QA_NAME(theTens ## 3)) \ |
270 | QA_DEFINECLASS(QA_NAME(theTens ## 5), QA_NAME(theTens ## 4)) \ |
271 | QA_DEFINECLASS(QA_NAME(theTens ## 6), QA_NAME(theTens ## 5)) \ |
272 | QA_DEFINECLASS(QA_NAME(theTens ## 7), QA_NAME(theTens ## 6)) \ |
273 | QA_DEFINECLASS(QA_NAME(theTens ## 8), QA_NAME(theTens ## 7)) \ |
274 | QA_DEFINECLASS(QA_NAME(theTens ## 9), QA_NAME(theTens ## 8)) |
275 | |
79104795 |
276 | QA_DEFINECLASS10(Transient_Root, 0) |
e8862cf4 |
277 | QA_DEFINECLASS10(qaclass09_50, 1) |
278 | QA_DEFINECLASS10(qaclass19_50, 2) |
279 | QA_DEFINECLASS10(qaclass29_50, 3) |
280 | QA_DEFINECLASS10(qaclass39_50, 4) |
281 | QA_DEFINECLASS (qaclass50_50, qaclass49_50) |
282 | |
283 | namespace |
284 | { |
285 | class qaclass50_50ANON : public qaclass49_50 |
286 | { |
287 | public: |
288 | qaclass50_50ANON() {} |
289 | }; |
290 | } |
291 | |
292 | namespace QaNamespace |
293 | { |
294 | class qaclass50_50 : public qaclass49_50 |
295 | { |
296 | public: |
297 | qaclass50_50() {} |
298 | }; |
299 | } |
300 | |
301 | namespace { |
302 | //! Timer sentry. Prints elapsed time information at destruction time. |
303 | class QATimer : public OSD_Timer |
304 | { |
305 | public: |
306 | enum TimeFormat |
307 | { |
308 | Seconds, |
309 | Milliseconds, |
310 | Microseconds, |
311 | Nanoseconds, |
312 | s = Seconds, |
313 | ms = Milliseconds, |
314 | ns = Nanoseconds, |
315 | }; |
316 | |
317 | public: |
318 | //! Main constructor - automatically starts the timer. |
319 | QATimer (Draw_Interpretor& theDI, |
320 | Standard_CString theTitle, |
321 | const TimeFormat theFormat, |
322 | const Standard_Integer theNbIters = 1, |
323 | const Standard_Boolean theToPrintFormat = Standard_False) |
324 | : myDI(&theDI), |
325 | myTitle (theTitle), |
326 | myFormat (theFormat), |
327 | myNbIters (theNbIters), |
328 | myToPrintFormat (theToPrintFormat) |
329 | { |
330 | Start(); |
331 | } |
332 | |
333 | //! Destructor - stops the timer and prints statistics. |
334 | ~QATimer() |
335 | { |
336 | Stop(); |
337 | if (myTitle != NULL) |
338 | { |
339 | (*myDI) << myTitle; |
340 | } |
341 | switch (myFormat) |
342 | { |
343 | case Seconds: |
344 | (*myDI) << ElapsedTime() / Standard_Real(myNbIters); |
345 | if (myToPrintFormat) |
346 | { |
347 | (*myDI) << " s"; |
348 | } |
349 | break; |
350 | case Milliseconds: |
351 | (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0; |
352 | if (myToPrintFormat) |
353 | { |
354 | (*myDI) << " ms"; |
355 | } |
356 | break; |
357 | case Microseconds: |
358 | (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0; |
359 | if (myToPrintFormat) |
360 | { |
361 | (*myDI) << " microseconds"; |
362 | } |
363 | break; |
364 | case Nanoseconds: |
365 | (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0; |
366 | if (myToPrintFormat) |
367 | { |
368 | (*myDI) << " ns"; |
369 | } |
370 | break; |
371 | } |
372 | } |
373 | |
374 | private: |
375 | Draw_Interpretor* myDI; |
376 | Standard_CString myTitle; //!< timer description |
377 | TimeFormat myFormat; //!< time format |
378 | Standard_Integer myNbIters; //!< iterations number |
379 | Standard_Boolean myToPrintFormat; //!< add time format |
380 | }; |
381 | } // anonymous namespace |
382 | |
383 | //======================================================================= |
384 | //function : QAHandleInc |
385 | //purpose : Estimate the smart-pointer counter incrementing time |
386 | //======================================================================= |
387 | static Standard_Integer QAHandleInc (Draw_Interpretor& theDI, |
388 | Standard_Integer theArgNb, |
389 | const char** theArgVec) |
390 | { |
391 | if (theArgNb > 2) |
392 | { |
393 | std::cout << "Error: wrong syntax! See usage:\n"; |
394 | theDI.PrintHelp (theArgVec[0]); |
395 | return 1; |
396 | } |
397 | const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi (theArgVec[1]) : 10000000; |
398 | if (aNbIters < 1) |
399 | { |
400 | std::cout << "Error: number of iterations should be positive!\n"; |
401 | return 1; |
402 | } |
403 | |
404 | Handle(Standard_Transient) aHandle = new Standard_Transient(); |
5b111128 |
405 | std::shared_ptr<Standard_Transient> aSharePtr (new Standard_Transient()); |
e8862cf4 |
406 | theDI << "Time of creating and destroying " << aNbIters << " smart pointers to the same object, per item, ns:"; |
407 | { |
408 | { |
409 | QATimer aTimer (theDI, "\nOCCT Handle: ", QATimer::ns, aNbIters); |
410 | { |
411 | std::vector<Handle(Standard_Transient)> aHandles (aNbIters); |
412 | for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter) |
413 | { |
414 | aHandles[anIter] = aHandle; |
415 | } |
416 | } |
417 | } |
418 | { |
419 | QATimer aTimer (theDI, "\nsC++ shared_ptr: ", QATimer::ns, aNbIters); |
420 | { |
5b111128 |
421 | std::vector< std::shared_ptr<Standard_Transient> > aSharePointers (aNbIters); |
e8862cf4 |
422 | for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter) |
423 | { |
424 | aSharePointers[anIter] = aSharePtr; |
425 | } |
426 | } |
427 | } |
428 | } |
429 | return 0; |
430 | } |
431 | |
432 | namespace |
433 | { |
434 | //! Auxiliary class to perform casting to specified type. |
435 | template<typename TTo> struct QACast |
436 | { |
437 | //! Perform casting using OCCT DownCast() operation. |
438 | template<typename TFrom> |
439 | static void doDownCast (Draw_Interpretor& theDI, |
440 | const Standard_Integer theNbIters, |
441 | const TFrom& theHandle) |
442 | { |
443 | std::vector<TTo> aHandles (theNbIters); |
444 | { |
445 | QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); |
446 | for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) |
447 | { |
448 | aHandles[anIter] = TTo::DownCast (theHandle); |
449 | } |
450 | } |
451 | } |
452 | |
453 | //! Perform casting using standard C++ dynamic_cast<> operation. |
454 | template<typename TFrom> |
455 | static void doDynamicCast (Draw_Interpretor& theDI, |
456 | const Standard_Integer theNbIters, |
457 | const TFrom& theHandle) |
458 | { |
459 | std::vector<typename TTo::element_type*> aPointers (theNbIters); |
460 | { |
461 | QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); |
462 | for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) |
463 | { |
464 | aPointers[anIter] = dynamic_cast<typename TTo::element_type* > (theHandle.operator->()); |
465 | } |
466 | } |
467 | } |
468 | |
469 | //! Perform dynamic casting using shared_ptr::dynamic_pointer_cast operation. |
470 | template<typename TFrom> |
471 | static void doShareCast (Draw_Interpretor& theDI, |
472 | const Standard_Integer theNbIters, |
5b111128 |
473 | const std::shared_ptr<TFrom>& theSharePtr) |
e8862cf4 |
474 | { |
5b111128 |
475 | std::vector< std::shared_ptr<typename TTo::element_type> > aSharePointers (theNbIters); |
e8862cf4 |
476 | { |
477 | QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); |
478 | for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) |
479 | { |
5b111128 |
480 | aSharePointers[anIter] = std::dynamic_pointer_cast<typename TTo::element_type, TFrom> (theSharePtr); |
e8862cf4 |
481 | } |
482 | } |
483 | } |
484 | |
485 | }; |
486 | |
487 | template<typename TAs> |
488 | static void qaCastAs (Draw_Interpretor& theDI, |
489 | const qaclass00_50& theInst, |
490 | const Standard_Integer theNbIters) |
491 | { |
492 | #define QA_TEST_CAST10(theTens, theDoCast) \ |
493 | QACast<QA_HANDLE_NAME(theTens ## 0)>::theDoCast(theDI, theNbIters, aPtr); \ |
1c29294e |
494 | QACast<QA_HANDLE_NAME(theTens ## 5)>::theDoCast(theDI, theNbIters, aPtr); |
495 | |
e8862cf4 |
496 | typedef typename TAs::element_type aPtrType; |
497 | TAs aDummy (new aPtrType()); |
498 | theDI << "Making a pointer:\n"; |
499 | theDI << aDummy->DynamicType()->Name() << "* ptr = new " << theInst.DynamicType()->Name() << "\n"; |
500 | theDI << "then measuring the time of casting it to base classes from qaclass00_50 to qaclass50_50, ns\n"; |
501 | if (!theInst.IsKind (aDummy->DynamicType())) |
502 | { |
503 | return; |
504 | } |
505 | |
506 | theDI << "\nOCCT Handle: "; |
507 | { |
508 | TAs aPtr ((typename TAs::element_type* )theInst.Clone()); |
509 | QA_TEST_CAST10(0, doDownCast); |
510 | QA_TEST_CAST10(1, doDownCast); |
511 | QA_TEST_CAST10(2, doDownCast); |
512 | QA_TEST_CAST10(3, doDownCast); |
513 | QA_TEST_CAST10(4, doDownCast); |
514 | QACast<Handle(qaclass50_50)>::doDownCast(theDI, theNbIters, aPtr); |
515 | } |
516 | theDI << "\nC++ dynamic_cast: "; |
517 | { |
518 | TAs aPtr ((typename TAs::element_type* )theInst.Clone()); |
519 | QA_TEST_CAST10(0, doDynamicCast); |
520 | QA_TEST_CAST10(1, doDynamicCast); |
521 | QA_TEST_CAST10(2, doDynamicCast); |
522 | QA_TEST_CAST10(3, doDynamicCast); |
523 | QA_TEST_CAST10(4, doDynamicCast); |
524 | QACast<Handle(qaclass50_50)>::doDynamicCast(theDI, theNbIters, aPtr); |
525 | } |
526 | theDI << "\nC++ dynamic_pointer_cast: "; |
527 | { |
5b111128 |
528 | std::shared_ptr<typename TAs::element_type> aPtr ((typename TAs::element_type* )theInst.Clone()); |
e8862cf4 |
529 | QA_TEST_CAST10(0, doShareCast); |
530 | QA_TEST_CAST10(1, doShareCast); |
531 | QA_TEST_CAST10(2, doShareCast); |
532 | QA_TEST_CAST10(3, doShareCast); |
533 | QA_TEST_CAST10(4, doShareCast); |
534 | QACast<Handle(qaclass50_50)>::doShareCast(theDI, theNbIters, aPtr); |
535 | } |
536 | } |
537 | |
538 | } |
539 | |
540 | //======================================================================= |
541 | //function : QAHandleCast |
542 | //purpose : Estimate performance of RTTI mechanisms - dynamic type casting |
543 | //======================================================================= |
544 | static Standard_Integer QAHandleCast (Draw_Interpretor& theDI, |
545 | Standard_Integer theArgNb, |
546 | const char** theArgVec) |
547 | { |
548 | if (theArgNb > 4) |
549 | { |
550 | std::cout << "Error: wrong syntax! See usage:\n"; |
551 | theDI.PrintHelp (theArgVec[0]); |
552 | return 1; |
553 | } |
554 | Standard_Integer anArgIter = 0; |
555 | const Standard_Integer anInst = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 50; |
556 | const Standard_Integer aPtrTo = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 0; |
557 | const Standard_Integer aNbIters = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 1000000; |
558 | |
559 | if (aNbIters < 1) |
560 | { |
561 | std::cout << "Error: number of iterations (" << aNbIters << ") should be positive!\n"; |
562 | return 1; |
563 | } |
564 | if (anInst > 50 || anInst < 0) |
565 | { |
566 | std::cout << "Error: class instance (" << anInst << ") should be specified within 0..50 range!\n"; |
567 | return 1; |
568 | } |
569 | if (aPtrTo > anInst || aPtrTo < 0) |
570 | { |
571 | std::cout << "Error: class pointer (" << aPtrTo << ") should be specified within 0.." << anInst << " range!\n"; |
572 | return 1; |
573 | } |
574 | else if (aPtrTo % 10 != 0) |
575 | { |
576 | std::cout << "Error: class pointer (" << aPtrTo << ") should be multiple of 10!\n"; |
577 | return 1; |
578 | } |
579 | |
580 | Handle(qaclass00_50) aHandle = new qaclass50_50(); |
581 | for (Standard_Integer anInstIter = 50 - anInst; anInstIter > 0; --anInstIter) |
582 | { |
583 | Handle(Standard_Transient) aParent (aHandle->CreateParent()); |
584 | aHandle = Handle(qaclass00_50)::DownCast (aParent); |
585 | } |
586 | |
587 | std::ios::fmtflags aFlags = std::cout.flags(); |
588 | std::cout.precision (5); |
589 | |
e8862cf4 |
590 | switch (aPtrTo) |
591 | { |
592 | // vc11 requires /bigobj option |
e8862cf4 |
593 | case 0: qaCastAs<Handle(qaclass00_50)>(theDI, *aHandle, aNbIters); break; |
594 | case 10: qaCastAs<Handle(qaclass10_50)>(theDI, *aHandle, aNbIters); break; |
595 | case 20: qaCastAs<Handle(qaclass20_50)>(theDI, *aHandle, aNbIters); break; |
596 | case 30: qaCastAs<Handle(qaclass30_50)>(theDI, *aHandle, aNbIters); break; |
597 | case 40: qaCastAs<Handle(qaclass40_50)>(theDI, *aHandle, aNbIters); break; |
598 | case 50: qaCastAs<Handle(qaclass50_50)>(theDI, *aHandle, aNbIters); break; |
599 | } |
600 | std::cout.setf (aFlags); |
601 | return 0; |
602 | } |
603 | |
604 | //======================================================================= |
605 | //function : QAHandleKind |
606 | //purpose : |
607 | //======================================================================= |
608 | static Standard_Integer QAHandleKind (Draw_Interpretor& /*theDI*/, |
609 | Standard_Integer /*theArgNb*/, |
610 | const char** /*theArgVec*/) |
611 | { |
612 | Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50); |
613 | Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50); |
614 | Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50); |
615 | Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50); |
616 | Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50); |
617 | Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50); |
618 | |
619 | Handle(qaclass00_50) aHandle = new qaclass40_50(); |
620 | |
621 | #define QA_CHECK(theDesc, theExpr, theValue) \ |
622 | {\ |
623 | const bool isTrue = !!(theExpr); \ |
624 | std::cout << theDesc << (isTrue ? " TRUE " : " FALSE ") << (isTrue == theValue ? " is OK\n" : " is Error\n"); \ |
625 | } |
626 | |
627 | std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n"; |
628 | for (Handle(Standard_Type) aType = aHandle->DynamicType(); ! aType.IsNull(); aType = aType->Parent()) |
629 | { |
630 | std::cout << " - " << aType->Name() << "\n"; |
631 | } |
632 | |
633 | QA_CHECK ("Name == qaclass40_50 : ", TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(), true); |
634 | |
635 | QA_CHECK ("IsKind (aType00) : ", aHandle->IsKind (aType00), true); |
636 | QA_CHECK ("IsKind (aType10) : ", aHandle->IsKind (aType10), true); |
637 | QA_CHECK ("IsKind (aType20) : ", aHandle->IsKind (aType20), true); |
638 | QA_CHECK ("IsKind (aType30) : ", aHandle->IsKind (aType30), true); |
639 | QA_CHECK ("IsKind (aType40) : ", aHandle->IsKind (aType40), true); |
640 | QA_CHECK ("IsKind (aType50) : ", aHandle->IsKind (aType50), false); |
641 | |
642 | QA_CHECK ("IsKind (\"qaclass00_50\"): ", aHandle->IsKind ("qaclass00_50"), true); |
643 | QA_CHECK ("IsKind (\"qaclass10_50\"): ", aHandle->IsKind ("qaclass10_50"), true); |
644 | QA_CHECK ("IsKind (\"qaclass20_50\"): ", aHandle->IsKind ("qaclass20_50"), true); |
645 | QA_CHECK ("IsKind (\"qaclass30_50\"): ", aHandle->IsKind ("qaclass30_50"), true); |
646 | QA_CHECK ("IsKind (\"qaclass40_50\"): ", aHandle->IsKind ("qaclass40_50"), true); |
647 | QA_CHECK ("IsKind (\"qaclass50_50\"): ", aHandle->IsKind ("qaclass50_50"), false); |
648 | |
649 | QA_CHECK ("IsInstance (aType00) : ", aHandle->IsInstance (aType00), false); |
650 | QA_CHECK ("IsInstance (aType10) : ", aHandle->IsInstance (aType10), false); |
651 | QA_CHECK ("IsInstance (aType20) : ", aHandle->IsInstance (aType20), false); |
652 | QA_CHECK ("IsInstance (aType30) : ", aHandle->IsInstance (aType30), false); |
653 | QA_CHECK ("IsInstance (aType40) : ", aHandle->IsInstance (aType40), true); |
654 | QA_CHECK ("IsInstance (aType50) : ", aHandle->IsInstance (aType50), false); |
655 | |
656 | #ifdef HAVE_CPP11 |
657 | std::cout << "\nC++11:\n"; |
658 | std::type_index aCppType = typeid(*aHandle.operator->()); |
659 | std::cout << "typeid().name() = '" << typeid(*aHandle.operator->()).name() << "'\n"; |
660 | #ifdef _MSC_VER |
661 | std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n"; |
662 | #endif |
663 | |
664 | std::cout << "[ANON]typeid().name() = '" << typeid(qaclass50_50ANON).name() << "'\n"; |
665 | #ifdef _MSC_VER |
666 | std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n"; |
667 | #endif |
668 | |
669 | std::cout << "[NS]typeid().name() = '" << typeid(QaNamespace::qaclass50_50).name() << "'\n"; |
670 | #ifdef _MSC_VER |
671 | std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name() << "'\n"; |
672 | #endif |
673 | |
674 | QA_CHECK ("is typeid (aType00) : ", typeid(*aHandle.operator->()) == typeid(qaclass00_50), false); |
675 | QA_CHECK ("is typeid (aType10) : ", typeid(*aHandle.operator->()) == typeid(qaclass10_50), false); |
676 | QA_CHECK ("is typeid (aType20) : ", typeid(*aHandle.operator->()) == typeid(qaclass20_50), false); |
677 | QA_CHECK ("is typeid (aType30) : ", typeid(*aHandle.operator->()) == typeid(qaclass30_50), false); |
678 | QA_CHECK ("is typeid (aType40) : ", typeid(*aHandle.operator->()) == typeid(qaclass40_50), true); |
679 | QA_CHECK ("is typeid (aType50) : ", typeid(*aHandle.operator->()) == typeid(qaclass50_50), false); |
680 | |
681 | QA_CHECK ("is type_index (aType00) : ", aCppType == typeid(qaclass00_50), false); |
682 | QA_CHECK ("is type_index (aType40) : ", aCppType == typeid(qaclass40_50), true); |
683 | |
684 | QA_CHECK ("IsClass(Standard_Transient): ", std::is_class<Standard_Transient>::value == !!STANDARD_TYPE(Standard_Transient)->IsClass(), true); |
685 | //QA_CHECK ("IsEnum (Message_Status) : ", std::is_enum<Message_Status>::value == !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true); |
686 | #endif |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | void QANCollection::CommandsHandle (Draw_Interpretor& theCommands) |
692 | { |
693 | const char* THE_GROUP = "QANCollection"; |
694 | theCommands.Add ("QAHandleBool", |
695 | "Test handle boolean operator", |
696 | __FILE__, QAHandleBool, THE_GROUP); |
697 | theCommands.Add ("QAHandleInc", |
698 | "QAHandleInc nbIter=1000000" |
699 | "\n\t\t: Test handle increment performance", |
700 | __FILE__, QAHandleInc, THE_GROUP); |
701 | theCommands.Add ("QAHandleCast", |
702 | "QAHandleCast [instance=50 [pointerTo=0 [nbIter=1000000]]]" |
703 | "\n\t\t: Test handle DownCast performance." |
704 | "\n\t\t: instance - specifies the depth of instantiated class" |
705 | "\n\t\t: pointerTo - specifies the depth of pointer class, where instance is stored into", |
706 | __FILE__, QAHandleCast, THE_GROUP); |
707 | theCommands.Add ("QAHandleKind", |
708 | "Test handle IsKind", |
709 | __FILE__, QAHandleKind, THE_GROUP); |
710 | theCommands.Add ("QAHandleOps", |
711 | "Test handle operations", |
712 | __FILE__, QAHandleOps, THE_GROUP); |
713 | return; |
714 | } |