From: abv Date: Tue, 30 Jun 2015 07:25:48 +0000 (+0300) Subject: 0024870: Provide OCCT RTTI test cases X-Git-Tag: V7_0_0_beta~451 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=e8862cf41a310e818707ab36a351363dba480d31 0024870: Provide OCCT RTTI test cases Test commands for checking performance and functionality of OCCT handles and RTTI added. New test case added for that: test perf fclasses handle. Implementation of opencascade::handle improved to enable compile-time error if two handles of incompatible types are compared. Comparison of handle to NULL is not possible any more; method IsNull() should be used instead. Method LDOM_MemManager::Doc() is removed to avoid cyclic dependency of headers; constructor of LDOM_Document(LDOM_MemManager&) is used directly instead. Inclusion of headers corrected for compilation after previous patch. --- diff --git a/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.hxx b/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.hxx index c330dcf3f7..aa8fbfad98 100644 --- a/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.hxx +++ b/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.hxx @@ -39,6 +39,9 @@ #include #include #include + +#include + class BRepTools_ReShape; class Standard_OutOfRange; class Standard_NoSuchObject; diff --git a/src/BRepLib/BRepLib_CheckCurveOnSurface.lxx b/src/BRepLib/BRepLib_CheckCurveOnSurface.lxx index c59a29e2a1..cc9a13efae 100644 --- a/src/BRepLib/BRepLib_CheckCurveOnSurface.lxx +++ b/src/BRepLib/BRepLib_CheckCurveOnSurface.lxx @@ -12,6 +12,9 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include +#include + //======================================================================= //function : Curve //purpose : diff --git a/src/BRepTools/BRepTools.hxx b/src/BRepTools/BRepTools.hxx index 9c2fee3ce8..9ef08d9c17 100644 --- a/src/BRepTools/BRepTools.hxx +++ b/src/BRepTools/BRepTools.hxx @@ -27,6 +27,9 @@ #include #include #include + +#include + class TopoDS_Face; class TopoDS_Wire; class TopoDS_Edge; diff --git a/src/BRepTools/BRepTools_Modifier.hxx b/src/BRepTools/BRepTools_Modifier.hxx index f78630f800..c604279fc9 100644 --- a/src/BRepTools/BRepTools_Modifier.hxx +++ b/src/BRepTools/BRepTools_Modifier.hxx @@ -24,6 +24,9 @@ #include #include #include + +#include + class Standard_NullObject; class Standard_NoSuchObject; class TopoDS_Shape; diff --git a/src/IntPatch/IntPatch_Point.hxx b/src/IntPatch/IntPatch_Point.hxx index 7fa3b89126..5c9367b765 100644 --- a/src/IntPatch/IntPatch_Point.hxx +++ b/src/IntPatch/IntPatch_Point.hxx @@ -25,8 +25,9 @@ #include #include #include +#include + class Adaptor3d_HVertex; -class Adaptor2d_HCurve2d; class Standard_DomainError; class gp_Pnt; class IntSurf_Transition; diff --git a/src/Interface/Interface_Graph.hxx b/src/Interface/Interface_Graph.hxx index b8cff39434..6eaa95f01d 100644 --- a/src/Interface/Interface_Graph.hxx +++ b/src/Interface/Interface_Graph.hxx @@ -21,14 +21,14 @@ #include #include +#include +#include + #include #include -#include #include -#include -#include #include -#include + class Interface_InterfaceModel; class Standard_DomainError; class Interface_GeneralLib; diff --git a/src/LDOM/LDOM_BasicAttribute.cxx b/src/LDOM/LDOM_BasicAttribute.cxx index 2623157430..19becdbad3 100644 --- a/src/LDOM/LDOM_BasicAttribute.cxx +++ b/src/LDOM/LDOM_BasicAttribute.cxx @@ -15,6 +15,7 @@ #include #include +#include //======================================================================= //function : LDOM_BasicAttribute diff --git a/src/LDOM/LDOM_BasicElement.cxx b/src/LDOM/LDOM_BasicElement.cxx index 6ac9d66577..b6334dbe57 100644 --- a/src/LDOM/LDOM_BasicElement.cxx +++ b/src/LDOM/LDOM_BasicElement.cxx @@ -19,6 +19,7 @@ #include #include #include +#include //======================================================================= //function : Create diff --git a/src/LDOM/LDOM_BasicText.cxx b/src/LDOM/LDOM_BasicText.cxx index b03bb9affb..fda597b96d 100644 --- a/src/LDOM/LDOM_BasicText.cxx +++ b/src/LDOM/LDOM_BasicText.cxx @@ -15,6 +15,7 @@ #include #include +#include //======================================================================= //function : LDOM_BasicText() diff --git a/src/LDOM/LDOM_Element.cxx b/src/LDOM/LDOM_Element.cxx index 2fe0f6219e..b3efa1698b 100644 --- a/src/LDOM/LDOM_Element.cxx +++ b/src/LDOM/LDOM_Element.cxx @@ -16,6 +16,7 @@ #include #include #include +#include #include diff --git a/src/LDOM/LDOM_MemManager.hxx b/src/LDOM/LDOM_MemManager.hxx index f2e15b4093..a6525c8f29 100644 --- a/src/LDOM/LDOM_MemManager.hxx +++ b/src/LDOM/LDOM_MemManager.hxx @@ -18,10 +18,11 @@ #include #include -#include +class LDOM_Document; class LDOM_BasicElement; class LDOM_MemManager; +class LDOMBasicString; // Define handle class for LDOM_MemManager DEFINE_STANDARD_HANDLE (LDOM_MemManager, MMgt_TShared) @@ -63,8 +64,8 @@ class LDOM_MemManager : public MMgt_TShared const Standard_Integer theHashValue, const char * theHashedStr); - LDOM_Document Doc () const - { return LDOM_Document (* this); } +// LDOM_Document Doc () const +// { return LDOM_Document (* this); } const LDOM_MemManager& Self () const { return * this; } diff --git a/src/LDOM/LDOM_Node.hxx b/src/LDOM/LDOM_Node.hxx index 008eb98d1f..0c247558df 100644 --- a/src/LDOM/LDOM_Node.hxx +++ b/src/LDOM/LDOM_Node.hxx @@ -22,9 +22,9 @@ #include #include #include +#include class LDOM_BasicNode; -class LDOM_MemManager; // LDOM_Node : base class for LDOM interface objects // references LDOM_BasicNode - the real data stored in Document diff --git a/src/QANCollection/FILES b/src/QANCollection/FILES index b7dbef3230..8025e6fc9a 100755 --- a/src/QANCollection/FILES +++ b/src/QANCollection/FILES @@ -2,6 +2,7 @@ FILES QANCollection.cxx QANCollection.hxx QANCollection_Alloc.cxx +QANCollection_Handle.cxx QANCollection_Common.cxx QANCollection_Common.hxx QANCollection_DataMapIteratorOfDataMapOfRealPnt.hxx diff --git a/src/QANCollection/QANCollection.cxx b/src/QANCollection/QANCollection.cxx index 9424e79573..4a69d8026a 100644 --- a/src/QANCollection/QANCollection.cxx +++ b/src/QANCollection/QANCollection.cxx @@ -23,5 +23,6 @@ void QANCollection::Commands (Draw_Interpretor& theCommands) QANCollection::CommandsTest (theCommands); QANCollection::CommandsPerf (theCommands); QANCollection::CommandsAlloc (theCommands); + QANCollection::CommandsHandle(theCommands); QANCollection::CommandsStl (theCommands); } diff --git a/src/QANCollection/QANCollection.hxx b/src/QANCollection/QANCollection.hxx index c5d31cca23..ddabc507ba 100644 --- a/src/QANCollection/QANCollection.hxx +++ b/src/QANCollection/QANCollection.hxx @@ -41,20 +41,7 @@ public: Standard_EXPORT static void CommandsStl (Draw_Interpretor& DI); - - - -protected: - - - - - -private: - - - - + Standard_EXPORT static void CommandsHandle (Draw_Interpretor& DI); }; diff --git a/src/QANCollection/QANCollection_Handle.cxx b/src/QANCollection/QANCollection_Handle.cxx new file mode 100644 index 0000000000..0ed5aecb80 --- /dev/null +++ b/src/QANCollection/QANCollection_Handle.cxx @@ -0,0 +1,730 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(__GNUC__) && __cplusplus < 201103L +#include +#endif + +// auxiliary macro to check and report status +#define CHECK(di,ok,what) di << "Checking " << what << (ok ? ": OK\n" : ": Error\n") + +//======================================================================= +//function : QAHandleOps +//purpose : Test Handle operations (mostly compile-time checks) +//======================================================================= + +// set of overloaded functions for checking resolution of arguments +inline void f (const Handle(Geom_Curve)&) {} +inline void func (const Handle(Geom_Curve)&) {} +inline void func (const Handle(Geom_BSplineCurve)&) {} +inline void func (const Handle(Geom_Surface)&) {} +inline void func (const Handle(gp_Pnt)&) {} +inline void func (const Handle(gp_XYZ)&) {} +inline void func (const Handle(gp_Trsf)&) {} + +inline void gunc (Handle(Geom_Curve)&) {} + +static Standard_Integer QAHandleOps (Draw_Interpretor& theDI, + Standard_Integer /*theArgNb*/, + const char** /*theArgVec*/) +{ + // =============================================================== + // Part 1: classes inheriting transient + // =============================================================== + + Handle(Geom_Line) aLine = new Geom_Line (gp::Origin(), gp::DZ()); + CHECK(theDI, ! aLine.IsNull(), "handle for non-null"); + + const Handle(Geom_Line)& cLine = aLine; // cast to self const ref + const Handle(Geom_Curve)& cCurve = aLine; // cast to base const ref + Geom_Line* pLine = aLine.get(); + const Geom_Line* cpLine = aLine.get(); + Geom_Line& rLine = *aLine; + const Geom_Line& crLine = *cLine; + Handle(Geom_Curve) aCurve = aLine; // copy from handle to derived type + aCurve = cLine; // assignment to handle of derived type + Handle(Geom_Line) dLine (cpLine); // copy from handle to derived type + + aLine = Handle(Geom_Line)::DownCast (cCurve); + CHECK(theDI, ! aLine.IsNull(), "down cast"); + + // comparison operators + CHECK(theDI, aLine == aLine, "equality of handle to itself"); + CHECK(theDI, cLine == cLine, "equality of const handle to itself"); + CHECK(theDI, aLine == cLine, "equality of const and non-const handle"); + CHECK(theDI, aLine == cCurve, "equality of handle and base handle"); + CHECK(theDI, aLine == pLine, "equality of handle and pointer"); + CHECK(theDI, pLine == aLine, "equality of pointer and handle"); + CHECK(theDI, aLine == cpLine, "equality of handle and const pointer"); + CHECK(theDI, cpLine == aLine, "equality of const pointer and handle"); + CHECK(theDI, &rLine == aLine, "equality of reference and handle"); + CHECK(theDI, &crLine == aLine, "equality of reference and handle"); + + Handle(Geom_Line) aLin2; + CHECK(theDI, aLine != aLin2, "inequality of handle to the same type handle"); + CHECK(theDI, aLin2 != cLine, "inequality of const and non-const handle"); + CHECK(theDI, aLin2 != cCurve, "inequality of handle and base handle"); + CHECK(theDI, aLin2 != pLine, "inequality of handle and pointer"); + CHECK(theDI, pLine != aLin2, "inequality of pointer and handle"); + CHECK(theDI, aLin2 != cpLine, "inequality of handle and const pointer"); + CHECK(theDI, cpLine != aLin2, "inequality of const pointer and handle"); + + Handle(Geom_Curve) aCur2; + CHECK(theDI, aLine != aCur2, "inequality of handles of different types"); + CHECK(theDI, aCur2 != cLine, "inequality of const and non-const handle"); + CHECK(theDI, aCur2 != cCurve, "inequality of handle and base handle"); + CHECK(theDI, aCur2 != pLine, "inequality of handle and pointer"); + CHECK(theDI, pLine != aCur2, "inequality of pointer and handle"); + CHECK(theDI, aCur2 != cpLine, "inequality of handle and const pointer"); + CHECK(theDI, cpLine != aCur2, "inequality of const pointer and handle"); + + // passing handle as reference to base class + f (aLine); + + // passing handle to overloaded function accepting handle to another type + // will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3) + func (aLine); + func (cLine); +#endif + + // passing handle as non-const reference to base type + // currently allowed for compatibility + gunc (aLine); + Handle(Geom_Curve)& aCurve2 = aLine; // cast to base non-const ref + (void)aCurve2; + + Handle(Geom_Line) qLine = cpLine; // constructor from const pointer -- could be made explicit... + + Handle(Geom_Surface) aSurf; + (void)aSurf; + +#if 0 + // each test in this section must cause compiler error + gunc (cLine); // passing const handle as non-const reference to base type + pLine = cLine.get(); // getting non-const pointer to contained object from const handle + Handle(Geom_Line) xLine = cCurve; // copy from handle to base type + Handle(Geom_BSplineCurve) aBSpl (new Geom_Line (gp::Origin(), gp::DX())); // construction from pointer to incompatible type + + CHECK(theDI, aLine == aSurf, "equality of handles of incompatible types"); + CHECK(theDI, aSurf == cLine, "equality of const and non-const handle"); + CHECK(theDI, aSurf == cCurve, "equality of handle and base handle"); + CHECK(theDI, aSurf == pLine, "equality of handle and pointer"); + CHECK(theDI, pLine == aSurf, "equality of pointer and handle"); + CHECK(theDI, aSurf == cpLine, "equality of handle and const pointer"); + CHECK(theDI, cpLine != aSurf, "equality of const pointer and handle"); + + CHECK(theDI, aLine != aSurf, "inequality of handles of incompatible types"); + CHECK(theDI, aSurf != cLine, "inequality of const and non-const handle"); + CHECK(theDI, aSurf != cCurve, "inequality of handle and base handle"); + CHECK(theDI, aSurf != pLine, "inequality of handle and pointer"); + CHECK(theDI, pLine != aSurf, "inequality of pointer and handle"); + CHECK(theDI, aSurf != cpLine, "inequality of handle and const pointer"); + CHECK(theDI, cpLine != aSurf, "inequality of const pointer and handle"); +#endif + + // =============================================================== + // Part 2: classes not inheriting transient + // =============================================================== +/* + Handle(gp_Pnt) aPnt = new gp_Pnt (gp::Origin()); + CHECK(theDI, ! aPnt.IsNull(), "handle for non-null"); + + const Handle(gp_Pnt)& cPnt = aPnt; // cast to self const ref +// const Handle(gp_XYZ)& cXYZ = aPnt; // cast to base const ref + gp_Pnt* pPnt = aPnt.get(); + const gp_Pnt* cpPnt = aPnt.get(); + gp_Pnt& rPnt = *aPnt; + const gp_Pnt& crPnt = *cPnt; +// Handle(gp_XYZ) aXYZ = aPnt; // copy from handle to derived type +// aXYZ = cPnt; // assignment to handle of derived type + +// aPnt = Handle(gp_Pnt)::DownCast (cXYZ); +// CHECK(theDI, ! aPnt.IsNull(), "down cast"); + + // comparison operators + CHECK(theDI, aPnt == aPnt, "equality of handle to itself"); + CHECK(theDI, cPnt == cPnt, "equality of const handle to itself"); + CHECK(theDI, aPnt == cPnt, "equality of const and non-const handle"); +// CHECK(theDI, aPnt == cXYZ, "equality of handle and base handle"); + CHECK(theDI, aPnt == pPnt, "equality of handle and pointer"); + CHECK(theDI, pPnt == aPnt, "equality of pointer and handle"); + CHECK(theDI, aPnt == cpPnt, "equality of handle and const pointer"); + CHECK(theDI, cpPnt == aPnt, "equality of const pointer and handle"); + CHECK(theDI, &rPnt == aPnt, "equality of reference and handle"); + CHECK(theDI, &crPnt == aPnt, "equality of reference and handle"); + + Handle(gp_Pnt) aPnt2; + CHECK(theDI, aPnt != aPnt2, "inequality of handle to the same type handle"); + CHECK(theDI, aPnt2 != cPnt, "inequality of const and non-const handle"); +// CHECK(theDI, aPnt2 != cXYZ, "inequality of handle and base handle"); + CHECK(theDI, aPnt2 != pPnt, "inequality of handle and pointer"); + CHECK(theDI, pPnt != aPnt2, "inequality of pointer and handle"); + CHECK(theDI, aPnt2 != cpPnt, "inequality of handle and const pointer"); + CHECK(theDI, cpPnt != aPnt2, "inequality of const pointer and handle"); + + Handle(gp_XYZ) aXYZ2; + CHECK(theDI, aLine != aPnt2, "inequality of handles of different types"); + CHECK(theDI, aXYZ2 != cPnt, "inequality of const and non-const handle"); +// CHECK(theDI, aXYZ2 != cXYZ, "inequality of handle and base handle"); +// CHECK(theDI, aXYZ2 != pPnt, "inequality of handle and pointer"); +// CHECK(theDI, pPnt != aXYZ2, "inequality of pointer and handle"); +// CHECK(theDI, aXYZ2 != cpPnt, "inequality of handle and const pointer"); +// CHECK(theDI, cpPnt != aXYZ2, "inequality of const pointer and handle"); + + // passing handle as reference to base class + func (aPnt); + func (cPnt); +*/ + return 0; +} + +//======================================================================= +//function : QAHandleBool +//purpose : Test Handle -> bool conversion +//======================================================================= +static Standard_Integer QAHandleBool (Draw_Interpretor& theDI, + Standard_Integer /*theArgNb*/, + const char** /*theArgVec*/) +{ + Handle(NCollection_BaseAllocator) aPtr = new NCollection_IncAllocator(); + + Handle(NCollection_IncAllocator) anInc = Handle(NCollection_IncAllocator)::DownCast (aPtr); + CHECK (theDI, ! anInc.IsNull(), "cast to NCollection_IncAllocator"); + + Handle(NCollection_BaseAllocator) anAlloc = Handle(NCollection_BaseAllocator)::DownCast (aPtr); + CHECK (theDI, ! anAlloc.IsNull(), "cast to NCollection_BaseAllocator"); + + Handle(NCollection_HeapAllocator) aHAlloc = Handle(NCollection_HeapAllocator)::DownCast (aPtr); + CHECK (theDI, aHAlloc.IsNull(), "cast to NCollection_HeapAllocator"); + + return 0; +} + +// Auxiliary macros to create hierarchy of 50 classes +#define QA_DEFINECLASS(theClass, theParent) \ +class theClass : public theParent \ +{ \ +public:\ + theClass() {}; \ + virtual ~theClass() {}; \ + virtual const char* Name() const { return #theClass; } \ + virtual Standard_Transient* CreateParent() const { return new theParent(); } \ + virtual Standard_Transient* Clone() const { return new theClass(); } \ + DEFINE_STANDARD_RTTI(theClass, theParent); \ +};\ +DEFINE_STANDARD_HANDLE (theClass, theParent) \ +IMPLEMENT_STANDARD_HANDLE (theClass, theParent) \ +IMPLEMENT_STANDARD_RTTIEXT(theClass, theParent) + +#define QA_NAME(theNum) qaclass ## theNum ## _ ## 50 +#define QA_HANDLE_NAME(theNum) Handle(qaclass ## theNum ## _ ## 50) + +#define QA_DEFINECLASS10(theParent, theTens) \ +QA_DEFINECLASS(QA_NAME(theTens ## 0), theParent) \ +QA_DEFINECLASS(QA_NAME(theTens ## 1), QA_NAME(theTens ## 0)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 2), QA_NAME(theTens ## 1)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 3), QA_NAME(theTens ## 2)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 4), QA_NAME(theTens ## 3)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 5), QA_NAME(theTens ## 4)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 6), QA_NAME(theTens ## 5)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 7), QA_NAME(theTens ## 6)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 8), QA_NAME(theTens ## 7)) \ +QA_DEFINECLASS(QA_NAME(theTens ## 9), QA_NAME(theTens ## 8)) + +QA_DEFINECLASS10(Standard_Transient, 0) +QA_DEFINECLASS10(qaclass09_50, 1) +QA_DEFINECLASS10(qaclass19_50, 2) +QA_DEFINECLASS10(qaclass29_50, 3) +QA_DEFINECLASS10(qaclass39_50, 4) +QA_DEFINECLASS (qaclass50_50, qaclass49_50) + +namespace +{ + class qaclass50_50ANON : public qaclass49_50 + { + public: + qaclass50_50ANON() {} + }; +} + +namespace QaNamespace +{ + class qaclass50_50 : public qaclass49_50 + { + public: + qaclass50_50() {} + }; +} + +namespace { +//! Timer sentry. Prints elapsed time information at destruction time. +class QATimer : public OSD_Timer +{ +public: + enum TimeFormat + { + Seconds, + Milliseconds, + Microseconds, + Nanoseconds, + s = Seconds, + ms = Milliseconds, + ns = Nanoseconds, + }; + +public: + //! Main constructor - automatically starts the timer. + QATimer (Draw_Interpretor& theDI, + Standard_CString theTitle, + const TimeFormat theFormat, + const Standard_Integer theNbIters = 1, + const Standard_Boolean theToPrintFormat = Standard_False) + : myDI(&theDI), + myTitle (theTitle), + myFormat (theFormat), + myNbIters (theNbIters), + myToPrintFormat (theToPrintFormat) + { + Start(); + } + + //! Destructor - stops the timer and prints statistics. + ~QATimer() + { + Stop(); + if (myTitle != NULL) + { + (*myDI) << myTitle; + } + switch (myFormat) + { + case Seconds: + (*myDI) << ElapsedTime() / Standard_Real(myNbIters); + if (myToPrintFormat) + { + (*myDI) << " s"; + } + break; + case Milliseconds: + (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0; + if (myToPrintFormat) + { + (*myDI) << " ms"; + } + break; + case Microseconds: + (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0; + if (myToPrintFormat) + { + (*myDI) << " microseconds"; + } + break; + case Nanoseconds: + (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0; + if (myToPrintFormat) + { + (*myDI) << " ns"; + } + break; + } + } + +private: + Draw_Interpretor* myDI; + Standard_CString myTitle; //!< timer description + TimeFormat myFormat; //!< time format + Standard_Integer myNbIters; //!< iterations number + Standard_Boolean myToPrintFormat; //!< add time format +}; +} // anonymous namespace + +//======================================================================= +//function : QAHandleInc +//purpose : Estimate the smart-pointer counter incrementing time +//======================================================================= +static Standard_Integer QAHandleInc (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) +{ + if (theArgNb > 2) + { + std::cout << "Error: wrong syntax! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi (theArgVec[1]) : 10000000; + if (aNbIters < 1) + { + std::cout << "Error: number of iterations should be positive!\n"; + return 1; + } + + Handle(Standard_Transient) aHandle = new Standard_Transient(); + std::tr1::shared_ptr aSharePtr (new Standard_Transient()); + theDI << "Time of creating and destroying " << aNbIters << " smart pointers to the same object, per item, ns:"; + { + { + QATimer aTimer (theDI, "\nOCCT Handle: ", QATimer::ns, aNbIters); + { + std::vector aHandles (aNbIters); + for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter) + { + aHandles[anIter] = aHandle; + } + } + } + { + QATimer aTimer (theDI, "\nsC++ shared_ptr: ", QATimer::ns, aNbIters); + { + std::vector< std::tr1::shared_ptr > aSharePointers (aNbIters); + for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter) + { + aSharePointers[anIter] = aSharePtr; + } + } + } + } + return 0; +} + +namespace +{ + //! Auxiliary class to perform casting to specified type. + template struct QACast + { + //! Perform casting using OCCT DownCast() operation. + template + static void doDownCast (Draw_Interpretor& theDI, + const Standard_Integer theNbIters, + const TFrom& theHandle) + { + std::vector aHandles (theNbIters); + { + QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); + for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) + { + aHandles[anIter] = TTo::DownCast (theHandle); + } + } + } + + //! Perform casting using standard C++ dynamic_cast<> operation. + template + static void doDynamicCast (Draw_Interpretor& theDI, + const Standard_Integer theNbIters, + const TFrom& theHandle) + { + std::vector aPointers (theNbIters); + { + QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); + for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) + { + aPointers[anIter] = dynamic_cast (theHandle.operator->()); + } + } + } + + //! Perform dynamic casting using shared_ptr::dynamic_pointer_cast operation. + template + static void doShareCast (Draw_Interpretor& theDI, + const Standard_Integer theNbIters, + const std::tr1::shared_ptr& theSharePtr) + { + std::vector< std::tr1::shared_ptr > aSharePointers (theNbIters); + { + QATimer aTimer (theDI, " ", QATimer::ns, theNbIters); + for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter) + { + aSharePointers[anIter] = std::tr1::dynamic_pointer_cast (theSharePtr); + } + } + } + + }; + + template + static void qaCastAs (Draw_Interpretor& theDI, + const qaclass00_50& theInst, + const Standard_Integer theNbIters) + { + #define QA_TEST_CAST10(theTens, theDoCast) \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); \ + QACast::theDoCast(theDI, theNbIters, aPtr); + + typedef typename TAs::element_type aPtrType; + TAs aDummy (new aPtrType()); + theDI << "Making a pointer:\n"; + theDI << aDummy->DynamicType()->Name() << "* ptr = new " << theInst.DynamicType()->Name() << "\n"; + theDI << "then measuring the time of casting it to base classes from qaclass00_50 to qaclass50_50, ns\n"; + if (!theInst.IsKind (aDummy->DynamicType())) + { + return; + } + + theDI << "\nOCCT Handle: "; + { + TAs aPtr ((typename TAs::element_type* )theInst.Clone()); + QA_TEST_CAST10(0, doDownCast); + QA_TEST_CAST10(1, doDownCast); + QA_TEST_CAST10(2, doDownCast); + QA_TEST_CAST10(3, doDownCast); + QA_TEST_CAST10(4, doDownCast); + QACast::doDownCast(theDI, theNbIters, aPtr); + } + theDI << "\nC++ dynamic_cast: "; + { + TAs aPtr ((typename TAs::element_type* )theInst.Clone()); + QA_TEST_CAST10(0, doDynamicCast); + QA_TEST_CAST10(1, doDynamicCast); + QA_TEST_CAST10(2, doDynamicCast); + QA_TEST_CAST10(3, doDynamicCast); + QA_TEST_CAST10(4, doDynamicCast); + QACast::doDynamicCast(theDI, theNbIters, aPtr); + } + theDI << "\nC++ dynamic_pointer_cast: "; + { + std::tr1::shared_ptr aPtr ((typename TAs::element_type* )theInst.Clone()); + QA_TEST_CAST10(0, doShareCast); + QA_TEST_CAST10(1, doShareCast); + QA_TEST_CAST10(2, doShareCast); + QA_TEST_CAST10(3, doShareCast); + QA_TEST_CAST10(4, doShareCast); + QACast::doShareCast(theDI, theNbIters, aPtr); + } + } + +} + +//======================================================================= +//function : QAHandleCast +//purpose : Estimate performance of RTTI mechanisms - dynamic type casting +//======================================================================= +static Standard_Integer QAHandleCast (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) +{ + if (theArgNb > 4) + { + std::cout << "Error: wrong syntax! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + Standard_Integer anArgIter = 0; + const Standard_Integer anInst = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 50; + const Standard_Integer aPtrTo = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 0; + const Standard_Integer aNbIters = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 1000000; + + if (aNbIters < 1) + { + std::cout << "Error: number of iterations (" << aNbIters << ") should be positive!\n"; + return 1; + } + if (anInst > 50 || anInst < 0) + { + std::cout << "Error: class instance (" << anInst << ") should be specified within 0..50 range!\n"; + return 1; + } + if (aPtrTo > anInst || aPtrTo < 0) + { + std::cout << "Error: class pointer (" << aPtrTo << ") should be specified within 0.." << anInst << " range!\n"; + return 1; + } + else if (aPtrTo % 10 != 0) + { + std::cout << "Error: class pointer (" << aPtrTo << ") should be multiple of 10!\n"; + return 1; + } + + Handle(qaclass00_50) aHandle = new qaclass50_50(); + for (Standard_Integer anInstIter = 50 - anInst; anInstIter > 0; --anInstIter) + { + Handle(Standard_Transient) aParent (aHandle->CreateParent()); + aHandle = Handle(qaclass00_50)::DownCast (aParent); + } + + std::ios::fmtflags aFlags = std::cout.flags(); + std::cout.precision (5); + + #define QA_TEST_CASTAS10(theTens) \ + case 10 * theTens + 0: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 1: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 2: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 3: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 4: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 5: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 6: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 7: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 8: qaCastAs(theDI, *aHandle, aNbIters); break; \ + case 10 * theTens + 9: qaCastAs(theDI, *aHandle, aNbIters); break; + + switch (aPtrTo) + { + // vc11 requires /bigobj option + //QA_TEST_CASTAS10(0) + //QA_TEST_CASTAS10(1) + //QA_TEST_CASTAS10(2) + //QA_TEST_CASTAS10(3) + //QA_TEST_CASTAS10(4) + case 0: qaCastAs(theDI, *aHandle, aNbIters); break; + case 10: qaCastAs(theDI, *aHandle, aNbIters); break; + case 20: qaCastAs(theDI, *aHandle, aNbIters); break; + case 30: qaCastAs(theDI, *aHandle, aNbIters); break; + case 40: qaCastAs(theDI, *aHandle, aNbIters); break; + case 50: qaCastAs(theDI, *aHandle, aNbIters); break; + } + std::cout.setf (aFlags); + return 0; +} + +//======================================================================= +//function : QAHandleKind +//purpose : +//======================================================================= +static Standard_Integer QAHandleKind (Draw_Interpretor& /*theDI*/, + Standard_Integer /*theArgNb*/, + const char** /*theArgVec*/) +{ + Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50); + Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50); + Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50); + Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50); + Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50); + Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50); + + Handle(qaclass00_50) aHandle = new qaclass40_50(); + + #define QA_CHECK(theDesc, theExpr, theValue) \ + {\ + const bool isTrue = !!(theExpr); \ + std::cout << theDesc << (isTrue ? " TRUE " : " FALSE ") << (isTrue == theValue ? " is OK\n" : " is Error\n"); \ + } + + std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n"; + for (Handle(Standard_Type) aType = aHandle->DynamicType(); ! aType.IsNull(); aType = aType->Parent()) + { + std::cout << " - " << aType->Name() << "\n"; + } + + QA_CHECK ("Name == qaclass40_50 : ", TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(), true); + + QA_CHECK ("IsKind (aType00) : ", aHandle->IsKind (aType00), true); + QA_CHECK ("IsKind (aType10) : ", aHandle->IsKind (aType10), true); + QA_CHECK ("IsKind (aType20) : ", aHandle->IsKind (aType20), true); + QA_CHECK ("IsKind (aType30) : ", aHandle->IsKind (aType30), true); + QA_CHECK ("IsKind (aType40) : ", aHandle->IsKind (aType40), true); + QA_CHECK ("IsKind (aType50) : ", aHandle->IsKind (aType50), false); + + QA_CHECK ("IsKind (\"qaclass00_50\"): ", aHandle->IsKind ("qaclass00_50"), true); + QA_CHECK ("IsKind (\"qaclass10_50\"): ", aHandle->IsKind ("qaclass10_50"), true); + QA_CHECK ("IsKind (\"qaclass20_50\"): ", aHandle->IsKind ("qaclass20_50"), true); + QA_CHECK ("IsKind (\"qaclass30_50\"): ", aHandle->IsKind ("qaclass30_50"), true); + QA_CHECK ("IsKind (\"qaclass40_50\"): ", aHandle->IsKind ("qaclass40_50"), true); + QA_CHECK ("IsKind (\"qaclass50_50\"): ", aHandle->IsKind ("qaclass50_50"), false); + + QA_CHECK ("IsInstance (aType00) : ", aHandle->IsInstance (aType00), false); + QA_CHECK ("IsInstance (aType10) : ", aHandle->IsInstance (aType10), false); + QA_CHECK ("IsInstance (aType20) : ", aHandle->IsInstance (aType20), false); + QA_CHECK ("IsInstance (aType30) : ", aHandle->IsInstance (aType30), false); + QA_CHECK ("IsInstance (aType40) : ", aHandle->IsInstance (aType40), true); + QA_CHECK ("IsInstance (aType50) : ", aHandle->IsInstance (aType50), false); + +#ifdef HAVE_CPP11 + std::cout << "\nC++11:\n"; + std::type_index aCppType = typeid(*aHandle.operator->()); + std::cout << "typeid().name() = '" << typeid(*aHandle.operator->()).name() << "'\n"; +#ifdef _MSC_VER + std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n"; +#endif + + std::cout << "[ANON]typeid().name() = '" << typeid(qaclass50_50ANON).name() << "'\n"; +#ifdef _MSC_VER + std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n"; +#endif + + std::cout << "[NS]typeid().name() = '" << typeid(QaNamespace::qaclass50_50).name() << "'\n"; +#ifdef _MSC_VER + std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name() << "'\n"; +#endif + + QA_CHECK ("is typeid (aType00) : ", typeid(*aHandle.operator->()) == typeid(qaclass00_50), false); + QA_CHECK ("is typeid (aType10) : ", typeid(*aHandle.operator->()) == typeid(qaclass10_50), false); + QA_CHECK ("is typeid (aType20) : ", typeid(*aHandle.operator->()) == typeid(qaclass20_50), false); + QA_CHECK ("is typeid (aType30) : ", typeid(*aHandle.operator->()) == typeid(qaclass30_50), false); + QA_CHECK ("is typeid (aType40) : ", typeid(*aHandle.operator->()) == typeid(qaclass40_50), true); + QA_CHECK ("is typeid (aType50) : ", typeid(*aHandle.operator->()) == typeid(qaclass50_50), false); + + QA_CHECK ("is type_index (aType00) : ", aCppType == typeid(qaclass00_50), false); + QA_CHECK ("is type_index (aType40) : ", aCppType == typeid(qaclass40_50), true); + + QA_CHECK ("IsClass(Standard_Transient): ", std::is_class::value == !!STANDARD_TYPE(Standard_Transient)->IsClass(), true); + //QA_CHECK ("IsEnum (Message_Status) : ", std::is_enum::value == !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true); +#endif + + return 0; +} + +void QANCollection::CommandsHandle (Draw_Interpretor& theCommands) +{ + const char* THE_GROUP = "QANCollection"; + theCommands.Add ("QAHandleBool", + "Test handle boolean operator", + __FILE__, QAHandleBool, THE_GROUP); + theCommands.Add ("QAHandleInc", + "QAHandleInc nbIter=1000000" + "\n\t\t: Test handle increment performance", + __FILE__, QAHandleInc, THE_GROUP); + theCommands.Add ("QAHandleCast", + "QAHandleCast [instance=50 [pointerTo=0 [nbIter=1000000]]]" + "\n\t\t: Test handle DownCast performance." + "\n\t\t: instance - specifies the depth of instantiated class" + "\n\t\t: pointerTo - specifies the depth of pointer class, where instance is stored into", + __FILE__, QAHandleCast, THE_GROUP); + theCommands.Add ("QAHandleKind", + "Test handle IsKind", + __FILE__, QAHandleKind, THE_GROUP); + theCommands.Add ("QAHandleOps", + "Test handle operations", + __FILE__, QAHandleOps, THE_GROUP); + return; +} diff --git a/src/RWStl/RWStl.hxx b/src/RWStl/RWStl.hxx index d1083c33ec..cbbbcf3289 100644 --- a/src/RWStl/RWStl.hxx +++ b/src/RWStl/RWStl.hxx @@ -20,12 +20,10 @@ #include #include #include +#include -#include class StlMesh_Mesh; class OSD_Path; -class Message_ProgressIndicator; - //! This package contains the methods to be used in //! the Stereo Lithograpy Application. The main diff --git a/src/ShapeFix/ShapeFix.hxx b/src/ShapeFix/ShapeFix.hxx index 4873d8a8b6..b371ad6627 100644 --- a/src/ShapeFix/ShapeFix.hxx +++ b/src/ShapeFix/ShapeFix.hxx @@ -23,6 +23,10 @@ #include #include + +#include +#include + class TopoDS_Shape; class Message_ProgressIndicator; class ShapeExtend_BasicMsgRegistrator; diff --git a/src/ShapeFix/ShapeFix_Root.hxx b/src/ShapeFix/ShapeFix_Root.hxx index 050786cafb..f12bcbd1c0 100644 --- a/src/ShapeFix/ShapeFix_Root.hxx +++ b/src/ShapeFix/ShapeFix_Root.hxx @@ -26,6 +26,9 @@ #include #include #include + +#include + class ShapeBuild_ReShape; class ShapeExtend_BasicMsgRegistrator; class TopoDS_Shape; diff --git a/src/ShapeFix/ShapeFix_Shape.hxx b/src/ShapeFix/ShapeFix_Shape.hxx index 377ff0cb94..19c3625e44 100644 --- a/src/ShapeFix/ShapeFix_Shape.hxx +++ b/src/ShapeFix/ShapeFix_Shape.hxx @@ -27,6 +27,9 @@ #include #include #include + +#include + class ShapeFix_Solid; class TopoDS_Shape; class Message_ProgressIndicator; diff --git a/src/Standard/Standard_Handle.hxx b/src/Standard/Standard_Handle.hxx index a89dc29256..5287770c8e 100644 --- a/src/Standard/Standard_Handle.hxx +++ b/src/Standard/Standard_Handle.hxx @@ -123,38 +123,42 @@ namespace opencascade { template bool operator== (const handle& theHandle) const { - return this->entity == theHandle.entity; + return get() == theHandle.get(); } //! Check for equality - bool operator== (const Standard_Transient *thePtr) const + template + bool operator== (const T2 *thePtr) const { - return this->entity == thePtr; + return get() == thePtr; } //! Check for equality - friend bool operator== (const Standard_Transient *left, const handle& right) + template + friend bool operator== (const T2 *left, const handle& right) { - return left == right.entity; + return left == right.get(); } //! Check for inequality template bool operator!= (const handle& theHandle) const { - return this->entity != theHandle.entity; + return get() != theHandle.get(); } //! Check for inequality - bool operator!= (const Standard_Transient *thePtr) const + template + bool operator!= (const T2 *thePtr) const { - return this->entity != thePtr; + return get() != thePtr; } //! Check for inequality - friend bool operator!= (const Standard_Transient *left, const handle& right) + template + friend bool operator!= (const T2 *left, const handle& right) { - return left != right.entity; + return left != right.get(); } //! Down casting operator diff --git a/src/StepShape/StepShape_Edge.hxx b/src/StepShape/StepShape_Edge.hxx index 00d55b8186..d839c39eda 100644 --- a/src/StepShape/StepShape_Edge.hxx +++ b/src/StepShape/StepShape_Edge.hxx @@ -21,9 +21,9 @@ #include #include -class StepShape_Vertex; -class TCollection_HAsciiString; +#include +class TCollection_HAsciiString; class StepShape_Edge; DEFINE_STANDARD_HANDLE(StepShape_Edge, StepShape_TopologicalRepresentationItem) diff --git a/src/XmlMDataStd/XmlMDataStd_ExtStringArrayDriver.cxx b/src/XmlMDataStd/XmlMDataStd_ExtStringArrayDriver.cxx index e4a13e2988..f18ab7bb40 100644 --- a/src/XmlMDataStd/XmlMDataStd_ExtStringArrayDriver.cxx +++ b/src/XmlMDataStd/XmlMDataStd_ExtStringArrayDriver.cxx @@ -155,7 +155,7 @@ void XmlMDataStd_ExtStringArrayDriver::Paste (const Handle(TDF_Attribute)& theSo anElement.setAttribute(::IsDeltaOn(), aExtStringArray->GetDelta()); // store a set of elements with string in each of them - XmlObjMgt_Document aDoc = anElement.getOwnerDocument().Doc(); + XmlObjMgt_Document aDoc (anElement.getOwnerDocument()); for ( Standard_Integer i = aL; i <= anU; i++ ) { diff --git a/src/XmlMDataStd/XmlMDataStd_ExtStringListDriver.cxx b/src/XmlMDataStd/XmlMDataStd_ExtStringListDriver.cxx index fa71a73bb7..b2a5b5bc99 100644 --- a/src/XmlMDataStd/XmlMDataStd_ExtStringListDriver.cxx +++ b/src/XmlMDataStd/XmlMDataStd_ExtStringListDriver.cxx @@ -126,7 +126,7 @@ void XmlMDataStd_ExtStringListDriver::Paste(const Handle(TDF_Attribute)& theSour XmlObjMgt_Element& anElement = theTarget; anElement.setAttribute(::LastIndexString(), anU); - XmlObjMgt_Document aDoc = anElement.getOwnerDocument().Doc(); + XmlObjMgt_Document aDoc (anElement.getOwnerDocument()); TDataStd_ListIteratorOfListOfExtendedString itr(anExtStringList->List()); for (; itr.More(); itr.Next()) diff --git a/src/XmlMDataStd/XmlMDataStd_NamedDataDriver.cxx b/src/XmlMDataStd/XmlMDataStd_NamedDataDriver.cxx index 465ecf07b6..2b0ace1a25 100644 --- a/src/XmlMDataStd/XmlMDataStd_NamedDataDriver.cxx +++ b/src/XmlMDataStd/XmlMDataStd_NamedDataDriver.cxx @@ -647,7 +647,7 @@ void XmlMDataStd_NamedDataDriver::Paste(const Handle(TDF_Attribute)& theSource, Standard_Integer i=0, up; XmlObjMgt_Element& anElement = theTarget; - XmlObjMgt_Document aDoc = anElement.getOwnerDocument().Doc(); + XmlObjMgt_Document aDoc (anElement.getOwnerDocument()); if(S->HasIntegers() && !S->GetIntegersContainer().IsEmpty()) { // store a set of elements with string in each of them up = S->GetIntegersContainer().Extent(); diff --git a/src/XmlMDataStd/XmlMDataStd_ReferenceArrayDriver.cxx b/src/XmlMDataStd/XmlMDataStd_ReferenceArrayDriver.cxx index 5c8f96f565..130fc93bd4 100644 --- a/src/XmlMDataStd/XmlMDataStd_ReferenceArrayDriver.cxx +++ b/src/XmlMDataStd/XmlMDataStd_ReferenceArrayDriver.cxx @@ -177,7 +177,7 @@ void XmlMDataStd_ReferenceArrayDriver::Paste(const Handle(TDF_Attribute)& theSou anElement.setAttribute(::FirstIndexString(), aL); anElement.setAttribute(::LastIndexString(), anU); - XmlObjMgt_Document aDoc = anElement.getOwnerDocument().Doc(); + XmlObjMgt_Document aDoc (anElement.getOwnerDocument()); for (Standard_Integer i = aL; i <= anU; i++) { diff --git a/src/XmlMDataStd/XmlMDataStd_ReferenceListDriver.cxx b/src/XmlMDataStd/XmlMDataStd_ReferenceListDriver.cxx index 5755b9019e..494300dbc4 100644 --- a/src/XmlMDataStd/XmlMDataStd_ReferenceListDriver.cxx +++ b/src/XmlMDataStd/XmlMDataStd_ReferenceListDriver.cxx @@ -175,7 +175,7 @@ void XmlMDataStd_ReferenceListDriver::Paste(const Handle(TDF_Attribute)& theSour XmlObjMgt_Element& anElement = theTarget; anElement.setAttribute(::LastIndexString(), anU); if(anU == 0) return; - XmlObjMgt_Document aDoc = anElement.getOwnerDocument().Doc(); + XmlObjMgt_Document aDoc (anElement.getOwnerDocument()); TDF_ListIteratorOfLabelList itr(aReferenceList->List()); for (; itr.More(); itr.Next()) diff --git a/src/XmlMFunction/XmlMFunction_ScopeDriver.cxx b/src/XmlMFunction/XmlMFunction_ScopeDriver.cxx index 5cad1909c0..a029af2462 100644 --- a/src/XmlMFunction/XmlMFunction_ScopeDriver.cxx +++ b/src/XmlMFunction/XmlMFunction_ScopeDriver.cxx @@ -261,7 +261,7 @@ void XmlMFunction_ScopeDriver::Paste (const Handle(TDF_Attribute)& theSource, XmlObjMgt_Element& anElement = theTarget; anElement.setAttribute(::LastLabelIndex(), S->GetFunctions().Extent()); - XmlObjMgt_Document aDoc = anElement.getOwnerDocument().Doc(); + XmlObjMgt_Document aDoc (anElement.getOwnerDocument()); for (itrd.Initialize(S->GetFunctions()); itrd.More(); itrd.Next()) { diff --git a/tests/perf/fclasses/handle b/tests/perf/fclasses/handle new file mode 100644 index 0000000000..8cf2bda53a --- /dev/null +++ b/tests/perf/fclasses/handle @@ -0,0 +1,53 @@ +puts "========" +puts "CR24023, check operability and performance of OCCT RTTI and handles" +puts "========" +puts "" + +pload QAcommands + +# check RTTI +QAHandleBool +QAHandleKind +QAHandleOps + +# check performance of creation and destruction handles, vs. C++ shared_ptr +set res [QAHandleInc] +set res_lines [split $res \n] +set time_occt [lindex [split [lindex $res_lines 1] :] end] +set time_std [lindex [split [lindex $res_lines 2] :] end] +set ratio [expr $time_occt / $time_std] + +# allow 5% deviation +if { $ratio > 1.05 } { + puts "Error: OCCT handle is too slow: $time_occt vs. $time_std of shared_ptr" +} + +# Check performance of down casting at different nesting depths. +# OCCT is expected to be at least twice faster on deep nesting on x64, +# however can be slower on 32-bit +set depths {3 5 10 50} +if { [regexp x86 [dversion]] } { + set thresholds {2. 1.5 1. 1.2} +} else { + set thresholds {1.6 1.1 0.7 0.5} +} +for {set i 0} {$i < [llength $depths]} {incr i} { + set depth [lindex $depths $i] + set threshold [lindex $thresholds $i] + puts "\nTesting DownCast at nesting depth $depth" + + set res [QAHandleCast $depth 0 100000] + set res_lines [split $res \n] + set time_occt [lindex [lindex [split [lindex $res_lines end-2] :] end] $depth] + set time_std [lindex [lindex [split [lindex $res_lines end-1] :] end] $depth] + set time_ptr [lindex [lindex [split [lindex $res_lines end ] :] end] $depth] + set ratio_std [expr $time_occt / $time_std] + set ratio_ptr [expr $time_occt / $time_ptr] + + puts "Ratio of time of OCCT DownCast() to dynamic_cast<>: $ratio_std" + puts "Ratio of time of OCCT DownCast() to dynamic_pointer_cast<>: $ratio_ptr" + + if { $ratio_std > $threshold || $ratio_ptr > $threshold } { + puts "Error: OCCT DownCast() is expected to be faster!" + } +} \ No newline at end of file