// -*- C++ -*- /*************************************************************************** * * memory - declarations for the Standard Library memory implementation * * $Id: memory 173524 2012-02-07 16:46:27Z ismith $ * *************************************************************************** * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * *************************************************************************** * * Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved. * * This computer software is owned by Rogue Wave Software, Inc. and is * protected by U.S. copyright laws and other laws and by international * treaties. This computer software is furnished by Rogue Wave Software, * Inc. pursuant to a written license agreement and may be used, copied, * transmitted, and stored only in accordance with the terms of such * license and with the inclusion of the above copyright notice. This * computer software or any other copies thereof may not be provided or * otherwise made available to any other person. * * U.S. Government Restricted Rights. This computer software is provided * with Restricted Rights. Use, duplication, or disclosure by the * Government is subject to restrictions as set forth in subparagraph (c) * (1) (ii) of The Rights in Technical Data and Computer Software clause * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the * Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19, * as applicable. Manufacturer is Rogue Wave Software, Inc., 5500 * Flatiron Parkway, Boulder, Colorado 80301 USA. * **************************************************************************/ #ifndef _RWSTD_MEMORY_INCLUDED #define _RWSTD_MEMORY_INCLUDED #include #include #include #include #include _RWSTD_NAMESPACE_BEGIN (__rw) // [de]allocate storage (in bytes) _RWSTD_EXPORT void* __rw_allocate (_RWSTD_C::size_t, int = 0); _RWSTD_EXPORT void __rw_deallocate (void*, _RWSTD_C::size_t, int = 0); // this function returns a suggested new capacity for a container needing // more room; see stddefs.h for an explanation of these macro parameters; // the _Container template parameter allows more specialized overloads // for customization template inline _RWSTD_C::size_t __rw_new_capacity (_RWSTD_C::size_t __size, const _Container*) { _RWSTD_C::size_t __cap = _RWSTD_STATIC_CAST (_RWSTD_C::size_t, _RWSTD_INCREASE_CAPACITY(__size) /*__size * _RWSTD_NEW_CAPACITY_RATIO*/); return (__size += _RWSTD_MINIMUM_NEW_CAPACITY) > __cap ? __size : __cap; } template inline void __rw_destroy (_TypeT &__ref) { __ref.~_TypeT (); } template inline void __rw_construct (_TypeT* __p, const _TypeU& __val) { new (__p) _TypeT (__val); } template void __rw_destroy (_ForwardIterator __first, _ForwardIterator __last) { for (; __first != __last; ++__first) __rw_destroy (*__first); } #ifndef _RWSTD_NO_PTR_VALUE_TEMPLATE_OVERLOAD // for compilers that don't optimize "empty" loops template inline void __rw_destroy (_TypeT**, _TypeT**) { } #endif // _RWSTD_NO_PTR_VALUE_TEMPLATE_OVERLOAD _RWSTD_NAMESPACE_END // __rw _RWSTD_NAMESPACE_BEGIN (std) template class allocator; _RWSTD_SPECIALIZED_CLASS class allocator { public: typedef void* pointer; typedef const void* const_pointer; typedef void value_type; #ifdef _RWSTD_ALLOCATOR template struct rebind { typedef allocator<_TypeU> other; }; #endif /* _RWSTD_ALLOCATOR */ }; template class allocator { public: typedef _RWSTD_C::size_t size_type; typedef ptrdiff_t difference_type; typedef _TypeT value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; allocator () _THROWS (()) { } allocator (const allocator &__rhs) _THROWS (()) { // working around an HP aCC warning 431 _RWSTD_UNUSED (__rhs); } #ifdef _RWSTD_ALLOCATOR template struct rebind { typedef allocator<_TypeU> other; }; template allocator (const allocator<_TypeU>&) _THROWS (()) { } template allocator& operator= (const allocator<_TypeU>&) _THROWS (()) { return *this; } #endif // _RWSTD_ALLOCATOR pointer address (reference __x) const { return &__x; } const_pointer address (const_reference __x) const { return &__x; } pointer allocate (size_type __n, allocator::const_pointer = 0) { #ifdef _RWSTD_ALLOCATOR return _RWSTD_STATIC_CAST (pointer, _RW::__rw_allocate (__n * sizeof (value_type))); #else return _RWSTD_STATIC_CAST (pointer, _RW::__rw_allocate (__n)); #endif // _RWSTD_ALLOCATOR } #ifdef _RWSTD_ALLOCATOR void deallocate (pointer __p, size_type __n) #else void deallocate (void* __p, size_type __n) #endif // _RWSTD_ALLOCATOR { _RW::__rw_deallocate (__p, __n); } // 20.4.1.1, p11 - the largest N for which allocate (N) might succeed size_type max_size () const _THROWS (()) { return size_type (~0) / sizeof (value_type) ? size_type (size_type (~0) / sizeof (value_type)) : size_type (1); } void construct (pointer __p, const_reference __val) { _RW::__rw_construct (__p, __val); } void destroy (pointer __p) { _RWSTD_ASSERT (0 != __p); _RW::__rw_destroy (*__p); } }; #if !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) \ && !defined (_RWSTD_NO_EXT_CONST_ALLOCATOR) // extension: allocates/constructs/destroys const elements template class allocator { public: typedef _RWSTD_C::size_t size_type; typedef ptrdiff_t difference_type; typedef const _TypeT value_type; typedef const value_type* pointer; typedef const value_type* const_pointer; typedef const value_type& reference; typedef const value_type& const_reference; allocator () _THROWS (()) { } allocator (const allocator &__rhs) _THROWS (()) { // working around an HP aCC warning 431 _RWSTD_UNUSED (__rhs); } #ifdef _RWSTD_ALLOCATOR template struct rebind { typedef allocator<_TypeU> other; }; template allocator (const allocator<_TypeU>&) _THROWS (()) { } template allocator& operator= (const allocator<_TypeU>&) _THROWS (()) { return *this; } #endif // _RWSTD_ALLOCATOR const_pointer address (const_reference __x) const { return &__x; } const_pointer allocate (size_type __n, allocator::const_pointer = 0) { #ifdef _RWSTD_ALLOCATOR return _RWSTD_STATIC_CAST (const_pointer, _RW::__rw_allocate (__n * sizeof (value_type))); #else return _RWSTD_STATIC_CAST (const_pointer, _RW::__rw_allocate (__n)); #endif // _RWSTD_ALLOCATOR } #ifdef _RWSTD_ALLOCATOR void deallocate (const_pointer __p, size_type __n /* elements */) #else void deallocate (const void* __p, size_type __n /* bytes */) #endif // _RWSTD_ALLOCATOR { _RW::__rw_deallocate (_RWSTD_CONST_CAST (_TypeT*, __p), __n); } // 20.4.1.1, p11 - the largest N for which allocate (N) might succeed size_type max_size () const _THROWS (()) { return ~size_type (0) / sizeof (value_type) ? size_type (size_type (~0) / sizeof (value_type)) : size_type (1); } void construct (const_pointer __p, const_reference __val) { _RW::__rw_construct (_RWSTD_CONST_CAST (_TypeT*, __p), __val); } void destroy (const_pointer __p) { _RWSTD_ASSERT (0 != __p); _RW::__rw_destroy (_RWSTD_CONST_CAST (_TypeT&, *__p)); } }; #endif // !_RWSTD_NO_CLASS_PARTIAL_SPEC && !_RWSTD_NO_EXT_CONST_ALLOCATOR) // allocator_interface provides all types and typed functions. Memory // allocated as raw bytes using the class provided by the Allocator // template parameter. allocator_interface casts appropriately. // // Multiple allocator_interface objects can attach to a single // allocator, thus allowing one allocator to allocate all storage // for a container, regardless of how many types are involved. // // The only real restriction is that pointer and reference are // hard coded as _TypeT* and _TypeT&. Partial specialization would // get around this. // #ifndef _RWSTD_ALLOCATOR template class allocator_interface { public: typedef _Allocator allocator_type; typedef _TypeT value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef _TYPENAME allocator_type::size_type size_type; typedef _TYPENAME allocator_type::difference_type difference_type; protected: allocator_type _C_alloc; public: allocator_interface() _THROWS (()) { } allocator_interface (const allocator_type &__alloc) _THROWS (()) : _C_alloc (__alloc) { } operator allocator_type& () { return _C_alloc; } pointer address (reference __x) { return &__x; } size_type max_size () const { return _C_alloc.max_size () / sizeof (value_type); } pointer allocate (size_type __n, const void* __p = 0) { //using c-style cast to perform reinterpret-cast & const-cast in 1 step return (pointer)_C_alloc.allocate (__n * sizeof (value_type), (pointer) __p ); } void deallocate (pointer __p, size_type __n) { _C_alloc.deallocate (__p, __n); } void construct (pointer __p, const_reference __val) const { _RW::__rw_construct(__p, __val); } void destroy (pointer __p) const { _RWSTD_ASSERT (0 != __p); _RW::__rw_destroy (*__p); } }; _RWSTD_SPECIALIZED_CLASS class allocator_interface, void> { public: typedef allocator allocator_type; typedef void* pointer; typedef const void* const_pointer; typedef void value_type; protected: allocator_type _C_alloc; public: allocator_interface () _THROWS (()) { } allocator_interface (const allocator& __rhs) _THROWS (()) : _C_alloc (__rhs) { } }; template inline bool operator== (const allocator_interface<_TypeT, _TypeU>&, const allocator_interface<_TypeV, _TypeW>&) _THROWS (()) { return true; } #endif // _RWSTD_ALLOCATOR template inline bool operator== (const allocator<_TypeT>&, const allocator<_TypeU>&) _THROWS (()) { return true; } #ifndef _RWSTD_NO_NAMESPACE template inline bool operator!= (const allocator<_TypeT>& __x, const allocator<_TypeU>& __y) _THROWS (()) { return !(__x == __y); } #endif // _RWSTD_NO_NAMESPACE // 20.4.2 template class raw_storage_iterator : public iterator { _OutputIterator _C_iter; public: // for completeness and genericity typedef _OutputIterator iterator_type; // 20.4.2, p2 _EXPLICIT raw_storage_iterator (iterator_type __x) : _C_iter (__x) { } // 20.4.2, p3 raw_storage_iterator& operator* () { return *this; } // 20.4.2, p4 raw_storage_iterator& operator= (const _TypeT& __rhs) { ::new (&(*_C_iter)) _TypeT (__rhs); return *this; } // 20.4.2, p6 raw_storage_iterator& operator++ () { ++_C_iter; return *this; } // 20.4.2, p7 raw_storage_iterator operator++ (int) { raw_storage_iterator __tmp = *this; ++*this; return __tmp; } }; _RWSTD_NAMESPACE_END // std _RWSTD_NAMESPACE_BEGIN (__rw) // __rw_indestructible specializations should be objects with static // storage duration that must "survive" all other static objects and that // do not need to be destroyed; this is a POD template class __rw_indestructible { union _C_data_t { char _C_data; // data to back _TypeT up with long double _C_padding; // make sure data is suitably aligned }; enum { _C_n = 1 + sizeof (_TypeT) / sizeof (_C_data_t) }; _C_data_t _C_data [_C_n]; // raw storage for an object of _TypeT public: typedef _TypeT value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef value_type* pointer; typedef const value_type* const_pointer; // no ctor to allow static POD initialization (3.6.2, p1) // allow this to be used as a an obejct of another type operator reference () { return _RWSTD_REINTERPRET_CAST (reference, *_C_data); } operator const_reference () const { return _RWSTD_REINTERPRET_CAST (const_reference, *_C_data); } // calls a conversion operator above pointer operator& () { // deprecated C-style cast used to make SunPro 5.0/T9 happy // return &_RWSTD_STATIC_CAST (reference, *this); return &(reference)*this; } // calls a conversion operator above const_pointer operator& () const { // deprecated C-style cast used to make SunPro 5.0/T9 happy // return &_RWSTD_STATIC_CAST (const_reference, *this); return &(const_reference)*this; } }; #ifdef _INLINE_WITH_STATICS _INLINE_WITH_STATICS _RWSTD_EXPORT char* __rw_get_static_buf () { typedef char _CharBuf [_RWSTD_TMPBUF_SIZE + 1]; // use `indestructible' to guarantee proper buffer alignment static __rw_indestructible<_CharBuf> __buffer; return _RWSTD_STATIC_CAST (char*, __buffer); } // [de]allocates a previously allocated temporary buffer // the constant _RWSTD_TMPBUF_SIZE controls the size of a static buffer // if request for area larger than _RWSTD_TMPBUF_SIZE comes in, // space is allocated dynamically, otherwise the static buffer is used // return value meaningful only if __n != 0 _INLINE_WITH_STATICS _RWSTD_EXPORT _STD::pair __rw_reallocate_temp_buffer (void *__p, _RWSTD_C::size_t __size) { // implicit initialization used to prevent a g++ 2.95.2 warning on Tru64 // sorry: semantics of inline function static data are wrong (you'll wind // up with multiple copies) static unsigned long __busy /* = 0 */; // > 0 when buffer in use unsigned long __cntr = _RWSTD_ATOMIC_PREINCREMENT (__busy, false); static char *__buffer = __rw_get_static_buf (); if (__p == (void*)__buffer) { __p = 0; __size = 0; // returning buffer, decrement usage counter _RWSTD_ATOMIC_PREDECREMENT (__busy, false); } else ::operator delete (__p); if (__size == 0) { // buffer not used, decrement usage counter _RWSTD_ATOMIC_PREDECREMENT (__busy, false); } else if (__size > _RWSTD_TMPBUF_SIZE || __cntr > 1) { _TRY { __p = ::operator new (__size); } _CATCH (...) { __p = 0; __size = 0; } // buffer not used, decrement usage counter _RWSTD_ATOMIC_PREDECREMENT (__busy, false); } else { __p = __buffer; // buffer used, usage counter stays non-zero } return _STD::pair(__p, __size); } #else // if !defined (_INLINE_WITH_STATICS) _STD::pair _RWSTD_EXPORT __rw_reallocate_temp_buffer (void*, _RWSTD_C::size_t); #endif // _INLINE_WITH_STATICS _RWSTD_NAMESPACE_END // __rw _RWSTD_NAMESPACE_BEGIN (std) // 20.4.3 only specifies a get_temporary_buffer<>() that takes a ptrdiff_t. // We overload on all types so that signed integral types other than ptrdiff_t // can be used. This is important in getting algorithms to compile with // user-defined iterators (not derived from iterator<...>) whose difference // type is something other than ptrdiff_t. // having this overload is important in some cases for compilers that // do not support partial class specialization (and where as a consequence // iterator_traits<> isn't available) template inline pair<_TypeT*, _Distance> get_temporary_buffer (_Distance __n, _TypeT*) { pair __pair = _RW::__rw_reallocate_temp_buffer (0, __n * sizeof (_TypeT)); return make_pair (_RWSTD_STATIC_CAST (_TypeT*, __pair.first), _Distance (__pair.second / sizeof (_TypeT))); } #ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE // 20.4.3, p1 template inline pair<_TypeT*, ptrdiff_t> get_temporary_buffer (ptrdiff_t __n) { return get_temporary_buffer (__n, (_TypeT*)0); } #endif // _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE // 20.4.3, p3 template inline void return_temporary_buffer (_TypeT *__p) { _RW::__rw_reallocate_temp_buffer (__p, 0); } // 20.4.4.1 template inline _ForwardIterator uninitialized_copy (_InputIterator __first, _InputIterator __last, _ForwardIterator __res) { _ForwardIterator __start = __res; _TRY { for (; __first != __last; ++__first, ++__res) _RW::__rw_construct (&*__res, *__first); } _CATCH (...) { _RW::__rw_destroy (__start, __res); _RETHROW; } return __res; } #ifdef _RWSTD_ALLOCATOR // extension template inline _ForwardIterator uninitialized_copy (_InputIterator __first, _InputIterator __last, _ForwardIterator __res, _Allocator& __alloc) { _ForwardIterator __start = __res; _TRY { for (; __first != __last; ++__first, ++__res) __alloc.construct (&*__res, *__first); } _CATCH (...) { for (; __start != __res; ++__start) __alloc.destroy (&*__start); _RETHROW; } return __res; } #endif // _RWSTD_ALLOCATOR // 20.4.4.2 template inline void uninitialized_fill (_ForwardIterator __first, _ForwardIterator __last, const _TypeT& __x) { _ForwardIterator __start = __first; _TRY { for (; __first != __last; ++__first) _RW::__rw_construct (&*__first, __x); } _CATCH (...) { _RW::__rw_destroy (__start, __first); _RETHROW; } } // 20.4.4.3 template inline void uninitialized_fill_n (_ForwardIterator __first, _Size __n, const _TypeT& __x) { _ForwardIterator __start = __first; _TRY { for (; __n; --__n, ++__first) _RW::__rw_construct (&*__first, __x); } _CATCH (...) { _RW::__rw_destroy (__start, __first); _RETHROW; } } #ifdef _RWSTD_ALLOCATOR // extension template inline void uninitialized_fill_n (_ForwardIter __first, _Size __n, const _TypeT& __x, _Allocator& __alloc) { _ForwardIter __start = __first; _TRY { for (; __n; --__n, ++__first) __alloc.construct (&*__first, __x); } _CATCH (...) { for (; __start != __first; ++__start) __alloc.destroy (&*__start); _RETHROW; } } #else // if !defined (_RWSTD_ALLOCATOR) // Specializations for non-standard allocators. When vector calls // uninitialized_{copy,fill_n} with non-standard allocator, a temporary // instance of allocator_interface is passed to these functions. Since // C++ forbids temporaries to be passed as non-const references, we // use these specializations to pass a const reference (and we can force // allocator_interface members construct & destroy to be const). template inline _ForwardIterator uninitialized_copy (_InputIterator __first, _InputIterator __last, _ForwardIterator __res, const allocator_interface<_Allocator, _TypeT>& __alloc) { _ForwardIterator __start = __res; _TRY { for (; __first != __last; ++__first, ++__res) __alloc.construct (&*__res, *__first); } _CATCH (...) { for (; __start != __res; ++__start) __alloc.destroy (&*__start); _RETHROW; } return __res; } template inline void uninitialized_fill_n (_ForwardIter __first, _Size __n, const _TypeT& __x, const allocator_interface<_Allocator, _TypeU>& __alloc) { _ForwardIter __start = __first; _TRY { for (; __n; --__n, ++__first) __alloc.construct (&*__first, __x); } _CATCH (...) { for (; __start != __first; ++__start) __alloc.destroy (&*__start); _RETHROW; } } #endif // _RWSTD_ALLOCATOR // 20.4.5 - Template class auto_ptr template class auto_ptr; // 20.4.5, p2 (defined outside of auto_ptr<> according to the proposed // resolution of lwg issue 127) template class auto_ptr_ref { public: auto_ptr<_TypeT>& _C_ptr; auto_ptr_ref (auto_ptr<_TypeT>& __rhs) : _C_ptr (__rhs) { } }; template class auto_ptr { public: typedef _TypeT element_type; _EXPLICIT auto_ptr (element_type* __p = 0) _THROWS (()) : _C_ptr (__p) { } auto_ptr (auto_ptr& __rhs) _THROWS (()) : _C_ptr (__rhs.release ()) { } auto_ptr& operator= (auto_ptr& __rhs) _THROWS (()) { reset (__rhs.release ()); return *this; } // follows lwg issue 127 auto_ptr& operator= (auto_ptr_ref __rhs) _THROWS (()) { reset (__rhs._C_ptr.release ()); return *this; } #ifndef _RWSTD_NO_MEMBER_TEMPLATES template operator auto_ptr_ref<_TypeU>() _THROWS (()) { return auto_ptr_ref<_TypeU>(*this); } template operator auto_ptr<_TypeU>() _THROWS (()) { return auto_ptr<_TypeU>(release ()); } template auto_ptr (auto_ptr<_TypeU>& __rhs) _THROWS (()) : _C_ptr (__rhs.release ()) { } template auto_ptr& operator= (auto_ptr<_TypeU>& __rhs) _THROWS (()) { reset (__rhs.release ()); return *this; } #endif // _RWSTD_NO_MEMBER_TEMPLATES ~auto_ptr () _THROWS (()) { delete _C_ptr; } element_type* get () const _THROWS (()) { return _C_ptr; } element_type& operator* () const _THROWS (()) { _RWSTD_ASSERT (0 != get ()); return *get (); } _RWSTD_OPERATOR_ARROW ( element_type* operator-> () const _THROWS (())) element_type* release () _THROWS (()) { element_type* __tmp = _C_ptr; _C_ptr = 0; return __tmp; } void reset (element_type* __p = 0) _THROWS (()) { if (_C_ptr != __p) { delete _C_ptr; _C_ptr = __p; } } auto_ptr (auto_ptr_ref __r) _THROWS (()) : _C_ptr (__r._C_ptr.release ()) { } private: element_type* _C_ptr; }; _RWSTD_NAMESPACE_END // std #endif // _RWSTD_MEMORY_INCLUDED