Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/pool/pool_alloc.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/pool/pool_alloc.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,488 @@ +// Copyright (C) 2000, 2001 Stephen Cleary +// Copyright (C) 2010 Paul A. Bristow added Doxygen comments. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_POOL_ALLOC_HPP +#define BOOST_POOL_ALLOC_HPP + +/*! + \file + \brief C++ Standard Library compatible pool-based allocators. + \details This header provides two template types - + \ref pool_allocator and \ref fast_pool_allocator - + that can be used for fast and efficient memory allocation + in conjunction with the C++ Standard Library containers. + + These types both satisfy the Standard Allocator requirements [20.1.5] + and the additional requirements in [20.1.5/4], + so they can be used with either Standard or user-supplied containers. + + In addition, the fast_pool_allocator also provides an additional allocation + and an additional deallocation function: + +<table> +<tr><th>Expression</th><th>Return Type</th><th>Semantic Equivalence<th></tr> +<tr><td><tt>PoolAlloc::allocate()</tt></td><td><tt>T *</tt></td><td><tt>PoolAlloc::allocate(1)</tt></tr> +<tr><td><tt>PoolAlloc::deallocate(p)</tt></td><td>void</tt></td><td><tt>PoolAlloc::deallocate(p, 1)</tt></tr> +</table> + +The typedef user_allocator publishes the value of the UserAllocator template parameter. + +<b>Notes</b> + +If the allocation functions run out of memory, they will throw <tt>std::bad_alloc</tt>. + +The underlying Pool type used by the allocators is accessible through the Singleton Pool Interface. +The identifying tag used for pool_allocator is pool_allocator_tag, +and the tag used for fast_pool_allocator is fast_pool_allocator_tag. +All template parameters of the allocators (including implementation-specific ones) +determine the type of the underlying Pool, +with the exception of the first parameter T, whose size is used instead. + +Since the size of T is used to determine the type of the underlying Pool, +each allocator for different types of the same size will share the same underlying pool. +The tag class prevents pools from being shared between pool_allocator and fast_pool_allocator. +For example, on a system where +<tt>sizeof(int) == sizeof(void *)</tt>, <tt>pool_allocator<int></tt> and <tt>pool_allocator<void *></tt> +will both allocate/deallocate from/to the same pool. + +If there is only one thread running before main() starts and after main() ends, +then both allocators are completely thread-safe. + +<b>Compiler and STL Notes</b> + +A number of common STL libraries contain bugs in their using of allocators. +Specifically, they pass null pointers to the deallocate function, +which is explicitly forbidden by the Standard [20.1.5 Table 32]. +PoolAlloc will work around these libraries if it detects them; +currently, workarounds are in place for: +Borland C++ (Builder and command-line compiler) +with default (RogueWave) library, ver. 5 and earlier, +STLport (with any compiler), ver. 4.0 and earlier. +*/ + +// std::numeric_limits +#include <boost/limits.hpp> +// new, std::bad_alloc +#include <new> + +#include <boost/throw_exception.hpp> +#include <boost/pool/poolfwd.hpp> + +// boost::singleton_pool +#include <boost/pool/singleton_pool.hpp> + +#include <boost/detail/workaround.hpp> + +#ifdef BOOST_POOL_INSTRUMENT +#include <iostream> +#include <iomanip> +#endif + +// The following code will be put into Boost.Config in a later revision +#if defined(_RWSTD_VER) || defined(__SGI_STL_PORT) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + #define BOOST_NO_PROPER_STL_DEALLOCATE +#endif + +namespace boost { + +#ifdef BOOST_POOL_INSTRUMENT + +template <bool b> +struct debug_info +{ + static unsigned allocated; +}; + +template <bool b> +unsigned debug_info<b>::allocated = 0; + +#endif + + //! Simple tag type used by pool_allocator as an argument to the + //! underlying singleton_pool. + struct pool_allocator_tag +{ +}; + +/*! \brief A C++ Standard Library conforming allocator, based on an underlying pool. + + Template parameters for pool_allocator are defined as follows: + + <b>T</b> Type of object to allocate/deallocate. + + <b>UserAllocator</B>. Defines the method that the underlying Pool will use to allocate memory from the system. See + <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details. + + <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying singleton_pool. + + <b>NextSize</b> The value of this parameter is passed to the underlying singleton_pool when it is created. + + <b>MaxSize</b> Limit on the maximum size used. + + \attention + The underlying singleton_pool used by the this allocator + constructs a pool instance that + <b>is never freed</b>. This means that memory allocated + by the allocator can be still used after main() has + completed, but may mean that some memory checking programs + will complain about leaks. + + + */ +template <typename T, + typename UserAllocator, + typename Mutex, + unsigned NextSize, + unsigned MaxSize > +class pool_allocator +{ + public: + typedef T value_type; //!< value_type of template parameter T. + typedef UserAllocator user_allocator; //!< allocator that defines the method that the underlying Pool will use to allocate memory from the system. + typedef Mutex mutex; //!< typedef mutex publishes the value of the template parameter Mutex. + BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< next_size publishes the values of the template parameter NextSize. + + typedef value_type * pointer; //!< + typedef const value_type * const_pointer; + typedef value_type & reference; + typedef const value_type & const_reference; + typedef typename pool<UserAllocator>::size_type size_type; + typedef typename pool<UserAllocator>::difference_type difference_type; + + //! \brief Nested class rebind allows for transformation from + //! pool_allocator<T> to pool_allocator<U>. + //! + //! Nested class rebind allows for transformation from + //! pool_allocator<T> to pool_allocator<U> via the member + //! typedef other. + template <typename U> + struct rebind + { // + typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other; + }; + + public: + pool_allocator() + { /*! Results in default construction of the underlying singleton_pool IFF an + instance of this allocator is constructed during global initialization ( + required to ensure construction of singleton_pool IFF an + instance of this allocator is constructed during global + initialization. See ticket #2359 for a complete explanation at + http://svn.boost.org/trac/boost/ticket/2359) . + */ + singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex, + NextSize, MaxSize>::is_from(0); + } + + // default copy constructor. + + // default assignment operator. + + // not explicit, mimicking std::allocator [20.4.1] + template <typename U> + pool_allocator(const pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &) + { /*! Results in the default construction of the underlying singleton_pool, this + is required to ensure construction of singleton_pool IFF an + instance of this allocator is constructed during global + initialization. See ticket #2359 for a complete explanation + at http://svn.boost.org/trac/boost/ticket/2359 . + */ + singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex, + NextSize, MaxSize>::is_from(0); + } + + // default destructor + + static pointer address(reference r) + { return &r; } + static const_pointer address(const_reference s) + { return &s; } + static size_type max_size() + { return (std::numeric_limits<size_type>::max)(); } + static void construct(const pointer ptr, const value_type & t) + { new (ptr) T(t); } + static void destroy(const pointer ptr) + { + ptr->~T(); + (void) ptr; // avoid unused variable warning. + } + + bool operator==(const pool_allocator &) const + { return true; } + bool operator!=(const pool_allocator &) const + { return false; } + + static pointer allocate(const size_type n) + { +#ifdef BOOST_POOL_INSTRUMENT + debug_info<true>::allocated += n * sizeof(T); + std::cout << "Allocating " << n << " * " << sizeof(T) << " bytes...\n" + "Total allocated is now " << debug_info<true>::allocated << std::endl; +#endif + const pointer ret = static_cast<pointer>( + singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex, + NextSize, MaxSize>::ordered_malloc(n) ); + if ((ret == 0) && n) + boost::throw_exception(std::bad_alloc()); + return ret; + } + static pointer allocate(const size_type n, const void * const) + { //! allocate n bytes + //! \param n bytes to allocate. + //! \param unused. + return allocate(n); + } + static void deallocate(const pointer ptr, const size_type n) + { //! Deallocate n bytes from ptr + //! \param ptr location to deallocate from. + //! \param n number of bytes to deallocate. +#ifdef BOOST_POOL_INSTRUMENT + debug_info<true>::allocated -= n * sizeof(T); + std::cout << "Deallocating " << n << " * " << sizeof(T) << " bytes...\n" + "Total allocated is now " << debug_info<true>::allocated << std::endl; +#endif +#ifdef BOOST_NO_PROPER_STL_DEALLOCATE + if (ptr == 0 || n == 0) + return; +#endif + singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex, + NextSize, MaxSize>::ordered_free(ptr, n); + } +}; + +/*! \brief Specialization of pool_allocator<void>. + +Specialization of pool_allocator for type void: required by the standard to make this a conforming allocator type. +*/ +template< + typename UserAllocator, + typename Mutex, + unsigned NextSize, + unsigned MaxSize> +class pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize> +{ +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + //! \brief Nested class rebind allows for transformation from + //! pool_allocator<T> to pool_allocator<U>. + //! + //! Nested class rebind allows for transformation from + //! pool_allocator<T> to pool_allocator<U> via the member + //! typedef other. + template <class U> + struct rebind + { + typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other; + }; +}; + +//! Simple tag type used by fast_pool_allocator as a template parameter to the underlying singleton_pool. +struct fast_pool_allocator_tag +{ +}; + + /*! \brief A C++ Standard Library conforming allocator geared towards allocating single chunks. + + While class template <tt>pool_allocator</tt> is a more general-purpose solution geared towards + efficiently servicing requests for any number of contiguous chunks, + <tt>fast_pool_allocator</tt> is also a general-purpose solution, + but is geared towards efficiently servicing requests for one chunk at a time; + it will work for contiguous chunks, but not as well as <tt>pool_allocator</tt>. + + If you are seriously concerned about performance, + use <tt>fast_pool_allocator</tt> when dealing with containers such as <tt>std::list</tt>, + and use <tt>pool_allocator</tt> when dealing with containers such as <tt>std::vector</tt>. + + The template parameters are defined as follows: + + <b>T</b> Type of object to allocate/deallocate. + + <b>UserAllocator</b>. Defines the method that the underlying Pool will use to allocate memory from the system. + See <a href="boost_pool/pool/pooling.html#boost_pool.pool.pooling.user_allocator">User Allocators</a> for details. + + <b>Mutex</b> Allows the user to determine the type of synchronization to be used on the underlying <tt>singleton_pool</tt>. + + <b>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created. + + <b>MaxSize</b> Limit on the maximum size used. + + \attention + The underlying singleton_pool used by the this allocator + constructs a pool instance that + <b>is never freed</b>. This means that memory allocated + by the allocator can be still used after main() has + completed, but may mean that some memory checking programs + will complain about leaks. + + */ + +template <typename T, + typename UserAllocator, + typename Mutex, + unsigned NextSize, + unsigned MaxSize > +class fast_pool_allocator +{ + public: + typedef T value_type; + typedef UserAllocator user_allocator; + typedef Mutex mutex; + BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); + + typedef value_type * pointer; + typedef const value_type * const_pointer; + typedef value_type & reference; + typedef const value_type & const_reference; + typedef typename pool<UserAllocator>::size_type size_type; + typedef typename pool<UserAllocator>::difference_type difference_type; + + //! \brief Nested class rebind allows for transformation from + //! fast_pool_allocator<T> to fast_pool_allocator<U>. + //! + //! Nested class rebind allows for transformation from + //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member + //! typedef other. + template <typename U> + struct rebind + { + typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other; + }; + + public: + fast_pool_allocator() + { + //! Ensures construction of the underlying singleton_pool IFF an + //! instance of this allocator is constructed during global + //! initialization. See ticket #2359 for a complete explanation + //! at http://svn.boost.org/trac/boost/ticket/2359 . + singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::is_from(0); + } + + // Default copy constructor used. + + // Default assignment operator used. + + // Not explicit, mimicking std::allocator [20.4.1] + template <typename U> + fast_pool_allocator( + const fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &) + { + //! Ensures construction of the underlying singleton_pool IFF an + //! instance of this allocator is constructed during global + //! initialization. See ticket #2359 for a complete explanation + //! at http://svn.boost.org/trac/boost/ticket/2359 . + singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::is_from(0); + } + + // Default destructor used. + + static pointer address(reference r) + { + return &r; + } + static const_pointer address(const_reference s) + { return &s; } + static size_type max_size() + { return (std::numeric_limits<size_type>::max)(); } + void construct(const pointer ptr, const value_type & t) + { new (ptr) T(t); } + void destroy(const pointer ptr) + { //! Destroy ptr using destructor. + ptr->~T(); + (void) ptr; // Avoid unused variable warning. + } + + bool operator==(const fast_pool_allocator &) const + { return true; } + bool operator!=(const fast_pool_allocator &) const + { return false; } + + static pointer allocate(const size_type n) + { + const pointer ret = (n == 1) ? + static_cast<pointer>( + (singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::malloc)() ) : + static_cast<pointer>( + singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::ordered_malloc(n) ); + if (ret == 0) + boost::throw_exception(std::bad_alloc()); + return ret; + } + static pointer allocate(const size_type n, const void * const) + { //! Allocate memory . + return allocate(n); + } + static pointer allocate() + { //! Allocate memory. + const pointer ret = static_cast<pointer>( + (singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::malloc)() ); + if (ret == 0) + boost::throw_exception(std::bad_alloc()); + return ret; + } + static void deallocate(const pointer ptr, const size_type n) + { //! Deallocate memory. + +#ifdef BOOST_NO_PROPER_STL_DEALLOCATE + if (ptr == 0 || n == 0) + return; +#endif + if (n == 1) + (singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr); + else + (singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr, n); + } + static void deallocate(const pointer ptr) + { //! deallocate/free + (singleton_pool<fast_pool_allocator_tag, sizeof(T), + UserAllocator, Mutex, NextSize, MaxSize>::free)(ptr); + } +}; + +/*! \brief Specialization of fast_pool_allocator<void>. + +Specialization of fast_pool_allocator<void> required to make the allocator standard-conforming. +*/ +template< + typename UserAllocator, + typename Mutex, + unsigned NextSize, + unsigned MaxSize > +class fast_pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize> +{ +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + //! \brief Nested class rebind allows for transformation from + //! fast_pool_allocator<T> to fast_pool_allocator<U>. + //! + //! Nested class rebind allows for transformation from + //! fast_pool_allocator<T> to fast_pool_allocator<U> via the member + //! typedef other. + template <class U> struct rebind + { + typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other; + }; +}; + +} // namespace boost + +#endif