From 2011028ee709cb5dc7a1fd340e1e5244fb660381 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 19 Jun 2008 20:38:38 +0000 Subject: [PATCH] From Neil Groves, "I have taken the liberty of updating a few files so that there is no longer any derivation from std::vector. I have done this by adding a new file osg/MixinVector and by updating only two others: osg/PrimitiveSet and osg/Array. You will notice that this actually removes what is acknowledged as a \u2018hack\u2019 in osg/PrimitiveSet. With the original code I did manage to find memory leaks with some compiler options on VC 8 and 9, as well as Intel compiler. I determined the leak existence by instrumenting the destructor code, and by use of a garbage collector as a leak detector (in a similar manner to the Firefox project). Hence in contrast to what I said originally, it is exhibiting symptoms on at least some platforms. Since I am trying to be a good OSG citizen I got out my editor and started hacking! I have built and tested on Linux (Ubuntu) with GCC 4.x and Windows VC 8 SP1. It appears that nothing is broken, and that I\u2019m using less memory J" --- include/osg/Array | 26 ++--- include/osg/MixinVector | 211 +++++++++++++++++++++++++++++++++++++++ include/osg/PrimitiveSet | 58 +---------- 3 files changed, 229 insertions(+), 66 deletions(-) create mode 100644 include/osg/MixinVector diff --git a/include/osg/Array b/include/osg/Array index 58063d42b..bf6c400cc 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -14,7 +14,7 @@ #ifndef OSG_ARRAY #define OSG_ARRAY 1 -#include +#include #include #include @@ -171,7 +171,7 @@ class OSG_EXPORT Array : public Object }; template -class TemplateArray : public Array, public std::vector +class TemplateArray : public Array, public MixinVector { public: @@ -179,20 +179,20 @@ class TemplateArray : public Array, public std::vector TemplateArray(const TemplateArray& ta,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Array(ta,copyop), - std::vector(ta) {} + MixinVector(ta) {} TemplateArray(unsigned int no) : Array(ARRAYTYPE,DataSize,DataType), - std::vector(no) {} + MixinVector(no) {} TemplateArray(unsigned int no,T* ptr) : Array(ARRAYTYPE,DataSize,DataType), - std::vector(ptr,ptr+no) {} + MixinVector(ptr,ptr+no) {} template TemplateArray(InputIterator first,InputIterator last) : Array(ARRAYTYPE,DataSize,DataType), - std::vector(first,last) {} + MixinVector(first,last) {} TemplateArray& operator = (const TemplateArray& array) { @@ -222,7 +222,7 @@ class TemplateArray : public Array, public std::vector /** Frees unused space on this vector - i.e. the difference between size() and max_size() of the underlying vector.*/ virtual void trim() { - std::vector( *this ).swap( *this ); + MixinVector( *this ).swap( *this ); } virtual const GLvoid* getDataPointer() const { if (!this->empty()) return &this->front(); else return 0; } @@ -257,7 +257,7 @@ class OSG_EXPORT IndexArray : public Array }; template -class TemplateIndexArray : public IndexArray, public std::vector +class TemplateIndexArray : public IndexArray, public MixinVector { public: @@ -265,20 +265,20 @@ class TemplateIndexArray : public IndexArray, public std::vector TemplateIndexArray(const TemplateIndexArray& ta,const CopyOp& copyop=CopyOp::SHALLOW_COPY): IndexArray(ta,copyop), - std::vector(ta) {} + MixinVector(ta) {} TemplateIndexArray(unsigned int no) : IndexArray(ARRAYTYPE,DataSize,DataType), - std::vector(no) {} + MixinVector(no) {} TemplateIndexArray(unsigned int no,T* ptr) : IndexArray(ARRAYTYPE,DataSize,DataType), - std::vector(ptr,ptr+no) {} + MixinVector(ptr,ptr+no) {} template TemplateIndexArray(InputIterator first,InputIterator last) : IndexArray(ARRAYTYPE,DataSize,DataType), - std::vector(first,last) {} + MixinVector(first,last) {} TemplateIndexArray& operator = (const TemplateIndexArray& array) { @@ -308,7 +308,7 @@ class TemplateIndexArray : public IndexArray, public std::vector /** Frees unused space on this vector - i.e. the difference between size() and max_size() of the underlying vector.*/ virtual void trim() { - std::vector( *this ).swap( *this ); + MixinVector( *this ).swap( *this ); } virtual const GLvoid* getDataPointer() const { if (!this->empty()) return &this->front(); else return 0; } diff --git a/include/osg/MixinVector b/include/osg/MixinVector new file mode 100644 index 000000000..cfa462aac --- /dev/null +++ b/include/osg/MixinVector @@ -0,0 +1,211 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_MIXIN_VECTOR +#define OSG_MIXIN_VECTOR 1 + +#include + +namespace osg { + +/** MixinVector is a base class that allows inheritance to be used to easily + * emulate derivation from std::vector but without introducing undefined + * behaviour through violation of virtual destructor rules. + * + * @author Neil Groves + */ +template > +class MixinVector +{ + typedef typename std::vector vector_type; +public: + typedef typename vector_type::allocator_type allocator_type; + typedef typename vector_type::value_type value_type; + typedef typename vector_type::const_pointer const_pointer; + typedef typename vector_type::pointer pointer; + typedef typename vector_type::const_reference const_reference; + typedef typename vector_type::reference reference; + typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::iterator iterator; + typedef typename vector_type::const_reverse_iterator const_reverse_iterator; + typedef typename vector_type::reverse_iterator reverse_iterator; + typedef typename vector_type::size_type size_type; + typedef typename vector_type::difference_type difference_type; + + explicit MixinVector(const allocator_type& alloc = allocator_type()) + : _impl(alloc) + { + } + + explicit MixinVector(size_type initial_size, const value_type& fill_value = value_type()) + : _impl(initial_size, fill_value) + { + } + + MixinVector(size_type initial_size, + const value_type& fill_value, + const allocator_type& alloc) + : _impl(initial_size, fill_value, alloc) + { + } + + template + MixinVector(InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()) + : _impl(first, last, alloc) + { + } + + MixinVector(const vector_type& other) + : _impl(other) + { + } + + MixinVector(const MixinVector& other) + : _impl(other._impl) + { + } + + MixinVector& operator=(const vector_type& other) + { + _impl = other; + return *this; + } + + MixinVector& operator=(const MixinVector& other) + { + _impl = other._impl; + return *this; + } + + virtual ~MixinVector() {} + + operator const vector_type&() const { return _impl; } + operator vector_type&() { return _impl; } + + void clear() { _impl.clear(); } + void resize(size_type new_size, const value_type& fill_value = value_type()) { _impl.resize(new_size, fill_value); } + void reserve(size_type new_capacity) { _impl.reserve(new_capacity); } + + void swap(vector_type& other) { _impl.swap(other); } + void swap(MixinVector& other) { _impl.swap(other._impl); } + + bool empty() const { return _impl.empty(); } + size_type size() const { return _impl.size(); } + size_type capacity() const { return _impl.capacity(); } + size_type max_size() const { return _impl.max_size(); } + allocator_type get_allocator() const { return _impl.get_allocator(); } + + const_iterator begin() const { return _impl.begin(); } + iterator begin() { return _impl.begin(); } + const_iterator end() const { return _impl.end(); } + iterator end() { return _impl.end(); } + + const_reverse_iterator rbegin() const { return _impl.rbegin(); } + reverse_iterator rbegin() { return _impl.rbegin(); } + const_reverse_iterator rend() const { return _impl.rend(); } + reverse_iterator rend() { return _impl.rend(); } + + const_reference operator[](size_type index) const { return _impl[index]; } + reference operator[](size_type index) { return _impl[index]; } + + const_reference at(size_type index) const { return _impl.at(index); } + reference at(size_type index) { return _impl.at(index); } + + void assign(size_type count, const value_type& value) { _impl.assign(count, value); } + template + void assign(Iter first, Iter last) { _impl.assign(first, last); } + + void push_back(const value_type& value) { _impl.push_back(value); } + void pop_back() { _impl.pop_back(); } + + iterator erase(iterator where) { return _impl.erase(where); } + iterator erase(iterator first, iterator last) { return _impl.erase(first, last); } + + iterator insert(iterator where, const value_type& value) { return _impl.insert(where, value); } + + template + void insert(iterator where, InputIterator first, InputIterator last) + { + _impl.insert(where, first, last); + } + + void insert(iterator where, size_type count, const value_type& value) + { + _impl.insert(where, count, value); + } + + const_reference back() const { return _impl.back(); } + reference back() { return _impl.back(); } + const_reference front() const { return _impl.front(); } + reference front() { return _impl.front(); } + + vector_type& asVector() { return _impl; } + const vector_type& asVector() const { return _impl; } + + friend inline bool operator==(const MixinVector& left, const MixinVector& right) { return left._impl == right._impl; } + friend inline bool operator==(const MixinVector& left, const std::vector& right) { return left._impl == right; } + friend inline bool operator==(const std::vector& left, const MixinVector& right) { return left == right._impl; } + + friend inline bool operator!=(const MixinVector& left, const MixinVector& right) { return left._impl != right._impl; } + friend inline bool operator!=(const MixinVector& left, const std::vector& right) { return left._impl != right; } + friend inline bool operator!=(const std::vector& left, const MixinVector& right) { return left != right._impl; } + + friend inline bool operator<(const MixinVector& left, const MixinVector& right) { return left._impl < right._impl; } + friend inline bool operator<(const MixinVector& left, const std::vector& right) { return left._impl < right; } + friend inline bool operator<(const std::vector& left, const MixinVector& right) { return left < right._impl; } + + friend inline bool operator>(const MixinVector& left, const MixinVector& right) { return left._impl > right._impl; } + friend inline bool operator>(const MixinVector& left, const std::vector& right) { return left._impl > right; } + friend inline bool operator>(const std::vector& left, const MixinVector& right) { return left > right._impl; } + + friend inline bool operator<=(const MixinVector& left, const MixinVector& right) { return left._impl <= right._impl; } + friend inline bool operator<=(const MixinVector& left, const std::vector& right) { return left._impl <= right; } + friend inline bool operator<=(const std::vector& left, const MixinVector& right) { return left <= right._impl; } + + friend inline bool operator>=(const MixinVector& left, const MixinVector& right) { return left._impl >= right._impl; } + friend inline bool operator>=(const MixinVector& left, const std::vector& right) { return left._impl >= right; } + friend inline bool operator>=(const std::vector& left, const MixinVector& right) { return left >= right._impl; } + +private: + vector_type _impl; +}; + +template inline +void +swap(MixinVector& left, + MixinVector& right) +{ + std::swap(left.asVector(), right.asVector()); +} + +template inline +void +swap(MixinVector& left, + std::vector& right) +{ + std::swap(left.asVector(), right); +} + +template inline +void +swap(std::vector& left, + MixinVector& right) +{ + std::swap(left, right.asVector()); +} + +} // namespace osg + +#endif + diff --git a/include/osg/PrimitiveSet b/include/osg/PrimitiveSet index 60e6bc0df..9d179aac8 100644 --- a/include/osg/PrimitiveSet +++ b/include/osg/PrimitiveSet @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -30,59 +31,10 @@ namespace osg { -// ******************************** HACK ********************************** -// Following classes are needed by VC++ in order to avoid linking errors due -// to multiply defined member functions. Classes that would normally derive -// from std::vector (and that are exported via OSG_EXPORT) should derive -// from one of these classes instead. -// -// NOTE: to keep the interface consistent and avoid breaking introspection -// wrappers, this hack was deliberately made not Microsoft-specific -// even though other compilers like GCC actually don't need that. -// -// Marco Jez, Dec 2005 - -class VectorGLsizei: public std::vector -{ - typedef std::vector vector_type; -public: - VectorGLsizei(): vector_type() {} - VectorGLsizei(const VectorGLsizei ©): vector_type(copy) {} - VectorGLsizei(GLsizei* beg, GLsizei* end): vector_type(beg, end) {} - explicit VectorGLsizei(unsigned int n): vector_type(n) {} -}; - -class VectorGLubyte: public std::vector -{ - typedef std::vector vector_type; -public: - VectorGLubyte(): vector_type() {} - VectorGLubyte(const VectorGLubyte ©): vector_type(copy) {} - VectorGLubyte(const GLubyte* beg, const GLubyte* end): vector_type(beg, end) {} - explicit VectorGLubyte(unsigned int n): vector_type(n) {} -}; - -class VectorGLushort: public std::vector -{ - typedef std::vector vector_type; -public: - VectorGLushort(): vector_type() {} - VectorGLushort(const VectorGLushort ©): vector_type(copy) {} - VectorGLushort(const GLushort* beg, const GLushort* end): vector_type(beg, end) {} - explicit VectorGLushort(unsigned int n): vector_type(n) {} -}; - -class VectorGLuint: public std::vector -{ - typedef std::vector vector_type; -public: - VectorGLuint(): vector_type() {} - VectorGLuint(const VectorGLuint ©): vector_type(copy) {} - VectorGLuint(const GLuint* beg, const GLuint* end): vector_type(beg, end) {} - explicit VectorGLuint(unsigned int n): vector_type(n) {} -}; - -// ************************************************************************** +typedef MixinVector VectorGLsizei; +typedef MixinVector VectorGLubyte; +typedef MixinVector VectorGLushort; +typedef MixinVector VectorGLuint; class State;