diff --git a/src/NCollection/FILES b/src/NCollection/FILES index ea23893cde..b5da38be75 100755 --- a/src/NCollection/FILES +++ b/src/NCollection/FILES @@ -6,6 +6,8 @@ NCollection_IncAllocator.hxx NCollection_IncAllocator.cxx NCollection_HeapAllocator.hxx NCollection_HeapAllocator.cxx +NCollection_StdAllocator.hxx + NCollection_ListNode.hxx NCollection_BaseList.hxx NCollection_BaseList.cxx diff --git a/src/NCollection/NCollection_StdAllocator.hxx b/src/NCollection/NCollection_StdAllocator.hxx new file mode 100644 index 0000000000..5a4edb6a74 --- /dev/null +++ b/src/NCollection/NCollection_StdAllocator.hxx @@ -0,0 +1,174 @@ +// Author: Roman Lygin, 2012. +// This file is put into Public Domain and thus can freely be used for any purpose. +// The author disclaims any rights and liabilities. + +#ifndef _NCollection_StdAllocator_HeaderFile +#define _NCollection_StdAllocator_HeaderFile + +#include + +#if _MSC_VER + //Workaround for false "unreferenced parameter" warning in destroy(). + #pragma warning (push) + #pragma warning (disable: 4100) +#endif + +//! Implements allocator requirements as defined in ISO C++ Standard 2003, section 20.1.5. +/*! The allocator uses instance of the NCollection_BaseAllocator (sub)class for memory + allocation/deallocation. The allocator can be used with standard + containers (std::vector, std::map, etc) to take advantage of NCollection_IncAllocator + which implements memory region concept, and hence to increase performance in specific + cases. + + The underlying NCollection_BaseAllocator instance can be received using the Allocator() + method. + + Example of use: + \code + Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator(); + NCollection_StdAllocator aSAlloc (anIncAlloc); + std::list > aL (aSAlloc); + TopoDS_Solid aSolid = BRepPrimAPI_MakeBox (10., 20., 30.); + aL.push_back (aSolid); + \endcode +*/ +template +class NCollection_StdAllocator { +public: + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template struct rebind { + typedef NCollection_StdAllocator other; + }; + + //! Constructor. + /*! Creates an object using default Open CASCADE allocation mechanism, i.e. which uses + Standard::Allocate() and Standard::Free() underneath. + */ + NCollection_StdAllocator() throw() + { myAlloc = NCollection_BaseAllocator::CommonBaseAllocator(); } + + //! Constructor. + /*! Saves \a theAlloc as an underlying allocator instance.*/ + NCollection_StdAllocator( const Handle(NCollection_BaseAllocator)& theAlloc) throw() + { myAlloc = theAlloc; } + + //! Constructor. + /*! Copies Allocator() from \a X.*/ + NCollection_StdAllocator( const NCollection_StdAllocator& X) throw() { myAlloc = X.myAlloc; } + + //! Destructor. + /*! Empty implementation.*/ + ~NCollection_StdAllocator() throw() {} + + //! Constructor. + /*! Copies Allocator() from \a Y.*/ + template NCollection_StdAllocator( const NCollection_StdAllocator& Y) throw() + { myAlloc = Y.Allocator(); } + + //! Returns an object address. + /*! Returns &x.*/ + pointer address( reference x ) const { return &x; } + + //! Returns an object address. + /*! Returns &x.*/ + const_pointer address( const_reference x ) const { return &x; } + + //! Allocates memory for \a n objects. + /*! Uses underlying allocator to allocate memory.*/ + pointer allocate( size_type n, const void* /*hint*/ = 0 ) + { return pointer( myAlloc->Allocate( n * sizeof( value_type ))); } + + //! Frees previously allocated memory. + /*! Uses underlying allocator to deallocate memory.*/ + void deallocate( pointer p, size_type ) { myAlloc->Free( p ); } + + //! Returns the largest value for which method allocate might succeed. + size_type max_size() const throw() + { + size_type aMax = static_cast( -1 ) / sizeof( value_type ); + return aMax; + } + + //! Constructs an object. + /*! Uses placement new operator and copy constructor to construct an object.*/ + void construct( pointer p, const_reference val ) + { new( static_cast( p )) value_type( val ); } + + //! Destroys the object. + /*! Uses object destructor.*/ + void destroy( pointer p ) { p->~value_type(); } + + //! Returns an underlying NCollection_BaseAllocator instance. + /*! Returns an object specified in the constructor.*/ + const Handle(NCollection_BaseAllocator)& Allocator() const { return myAlloc; } + +protected: + Handle(NCollection_BaseAllocator) myAlloc; +}; + +#if _MSC_VER + #pragma warning (pop) +#endif + + +//! Implements specialization NCollection_StdAllocator. +/*! Specialization is of low value and should normally be avoided in favor of a typed specialization. + + Example of use: + \code + Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator(); + NCollection_StdAllocator aVAlloc (anIncAlloc); + std::vector > aV3 (aVAlloc); + aV3.push_back (10.); + \endcode +*/ +template<> +class NCollection_StdAllocator { +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template struct rebind { + typedef NCollection_StdAllocator other; + }; + + //! Constructor. + /*! Creates an object using default Open CASCADE allocation mechanism, i.e. which uses + Standard::Allocate() and Standard::Free() underneath. + */ + NCollection_StdAllocator() throw() + { myAlloc = NCollection_BaseAllocator::CommonBaseAllocator(); } + + //! Constructor. + /*! Saves \a theAlloc as an underlying allocator instance.*/ + NCollection_StdAllocator( const Handle(NCollection_BaseAllocator)& theAlloc) throw() + { myAlloc = theAlloc; } + + //! Constructor. + /*! Copies Allocator() from \a X.*/ + NCollection_StdAllocator( const NCollection_StdAllocator& X) throw() { myAlloc = X.myAlloc; } + + //! Returns an underlying NCollection_BaseAllocator instance. + /*! Returns an object specified in the constructor.*/ + const Handle(NCollection_BaseAllocator)& Allocator() const { return myAlloc; } + +protected: + Handle(NCollection_BaseAllocator) myAlloc; +}; + +template +inline bool operator==( const NCollection_StdAllocator& X, const NCollection_StdAllocator& Y) +{ return !!(X.Allocator() == Y.Allocator()); } + +template +inline bool operator!=( const NCollection_StdAllocator& X, const NCollection_StdAllocator& Y) +{ return !(X == Y); } + + +#endif diff --git a/src/QANCollection/FILES b/src/QANCollection/FILES index 590efdfddf..0e7de083d5 100755 --- a/src/QANCollection/FILES +++ b/src/QANCollection/FILES @@ -4,6 +4,7 @@ QANCollection.cxx QANCollection1.cxx QANCollection2.cxx QANCollection3.cxx +QANCollection4.cxx QANCollection_Common.cxx QANCollection_Common.hxx QANCollection_Common2.hxx @@ -17,4 +18,4 @@ QANCollection_PerfLists.hxx QANCollection_PerfMaps.hxx QANCollection_PerfTest.hxx QANCollectionTest.cxx -QANCollection_PerfSparseArray.hxx \ No newline at end of file +QANCollection_PerfSparseArray.hxx diff --git a/src/QANCollection/QANCollection.cdl b/src/QANCollection/QANCollection.cdl index 0d1b63fb14..c6d54cf546 100755 --- a/src/QANCollection/QANCollection.cdl +++ b/src/QANCollection/QANCollection.cdl @@ -58,5 +58,6 @@ is Commands1(DI : in out Interpretor from Draw); Commands2(DI : in out Interpretor from Draw); Commands3(DI : in out Interpretor from Draw); + Commands4(DI : in out Interpretor from Draw); end; diff --git a/src/QANCollection/QANCollection.cxx b/src/QANCollection/QANCollection.cxx index 1d5ccc4b92..303d48cef8 100755 --- a/src/QANCollection/QANCollection.cxx +++ b/src/QANCollection/QANCollection.cxx @@ -29,5 +29,6 @@ void QANCollection::Commands(Draw_Interpretor& theCommands) { QANCollection::Commands1(theCommands); QANCollection::Commands2(theCommands); QANCollection::Commands3(theCommands); + QANCollection::Commands4(theCommands); return; } diff --git a/src/QANCollection/QANCollection4.cxx b/src/QANCollection/QANCollection4.cxx new file mode 100755 index 0000000000..48b27a5ca5 --- /dev/null +++ b/src/QANCollection/QANCollection4.cxx @@ -0,0 +1,154 @@ +// Created on: 2004-03-05 +// Created by: Mikhail KUZMITCHEV +// Copyright (c) 2004-2012 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + + + +#include +#include + +#include +#include +#include +#include + +//======================================================================= +//function : QANColStdAllocator1 +//purpose : +//======================================================================= +static Standard_Integer QANColStdAllocator1(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) +{ + if ( argc != 1) { + di << "Usage : " << argv[0] << "\n"; + return 1; + } + + //type definitions + typedef Handle_Standard_Transient elem_type; + typedef NCollection_StdAllocator allocator_type; + if ( sizeof (allocator_type::value_type) == sizeof (elem_type) ) { + di << "value_type : OK\n"; + } else { + di << "value_type : Error\n"; + } + if ( sizeof (allocator_type::pointer) == sizeof (void*) ) { + di << "pointer : OK\n"; + } else { + di << "pointer : Error\n"; + } + if (sizeof (allocator_type::const_pointer) == sizeof (void*) ) { + di << "const_pointer : OK\n"; + } else { + di << "const_pointer : Error\n"; + } + + elem_type aDummy; + allocator_type::reference aRef = aDummy; + allocator_type::const_reference aConstRef = aDummy; + if ( sizeof (allocator_type::size_type) == sizeof (size_t) ) { + di << "size_type : OK\n"; + } else { + di << "size_type : Error\n"; + } + if ( sizeof (allocator_type::difference_type) == sizeof (ptrdiff_t) ) { + di << "allocator_type : OK\n"; + } else { + di << "allocator_type : Error\n"; + } + + typedef int other_elem_type; + if ( sizeof (allocator_type::rebind::other::value_type) == sizeof (other_elem_type) ) { + di << "other_elem_type : OK\n"; + } else { + di << "other_elem_type : Error\n"; + } + + return 0; +} + +//======================================================================= +//function : QANColStdAllocator2 +//purpose : +//======================================================================= +static Standard_Integer QANColStdAllocator2(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) +{ + if ( argc != 1) { + di << "Usage : " << argv[0] << "\n"; + return 1; + } + + //create incremental allocator outside the scope of objects it will manage + Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator(); + + { + //typed allocator + NCollection_StdAllocator aSAlloc (anIncAlloc); + std::list > aL (aSAlloc); + aL.push_back (2); + if ( aL.size() == size_t (1) ) { + di << "Test1 : OK\n"; + } else { + di << "Test1 : Error\n"; + } + + //type cast + NCollection_StdAllocator aCAlloc; + std::vector > aV (aCAlloc); + aV.push_back (1); + if ( aV.size() == size_t (1) ) { + di << "Test2 : OK\n"; + } else { + di << "Test2 : Error\n"; + } + + //using void-specialization allocator + std::vector > aV2; + aV2.resize (10); + aV2.push_back (-1); + if ( aV2.size() == size_t (11) ) { + di << "Test3 : OK\n"; + } else { + di << "Test3 : Error\n"; + } + + //equality of allocators + if ( aSAlloc != aCAlloc ) { + di << "Test4 : OK\n"; + } else { + di << "Test4 : Error\n"; + } + NCollection_StdAllocator anIAlloc (anIncAlloc); + if ( aSAlloc == anIAlloc ) { + di << "Test5 : OK\n"; + } else { + di << "Test5 : Error\n"; + } + + } + + return 0; +} + +void QANCollection::Commands4(Draw_Interpretor& theCommands) { + const char *group = "QANCollection"; + + theCommands.Add("QANColStdAllocator1", "QANColStdAllocator1", __FILE__, QANColStdAllocator1, group); + theCommands.Add("QANColStdAllocator2", "QANColStdAllocator2", __FILE__, QANColStdAllocator2, group); + + return; +} diff --git a/tests/bugs/fclasses/bug23569_1 b/tests/bugs/fclasses/bug23569_1 new file mode 100755 index 0000000000..56a530f1f8 --- /dev/null +++ b/tests/bugs/fclasses/bug23569_1 @@ -0,0 +1,9 @@ +puts "=======" +puts "OCC23569" +puts "=======" +puts "" +########################################################################### +## Adding NCollection_StdAllocator +########################################################################### + +QANColStdAllocator1 diff --git a/tests/bugs/fclasses/bug23569_2 b/tests/bugs/fclasses/bug23569_2 new file mode 100755 index 0000000000..2ab7ec408c --- /dev/null +++ b/tests/bugs/fclasses/bug23569_2 @@ -0,0 +1,9 @@ +puts "=======" +puts "OCC23569" +puts "=======" +puts "" +########################################################################### +## Adding NCollection_StdAllocator +########################################################################### + +QANColStdAllocator2