|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r73495 - in branches/release: boost/pool boost/pool/detail libs/pool libs/pool/doc libs/pool/doc/html libs/pool/doc/html/boost libs/pool/doc/html/boost/fast_pool_allocator libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880 libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284 libs/pool/doc/html/boost/pool_allocator libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365 libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769 libs/pool/doc/html/boost/singleton_pool libs/pool/doc/html/boost_pool libs/pool/doc/html/boost_pool/appendices libs/pool/doc/html/boost_pool/indexes libs/pool/doc/html/boost_pool/pool libs/pool/doc/html/header libs/pool/doc/html/header/boost libs/pool/doc/html/header/boost/pool libs/pool/doc/images libs/pool/doc/implementation libs/pool/doc/interfaces libs/pool/example libs/pool/test
From: john_at_[hidden]
Date: 2011-08-02 13:04:10
Author: johnmaddock
Date: 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
New Revision: 73495
URL: http://svn.boost.org/trac/boost/changeset/73495
Log:
Merge updated Pool lib from trunk.
Fixes #1252.
Fixes #2696.
Fixes #4960.
Fixes #5526.
Fixes #5568.
Fixes #5700.
Added:
branches/release/boost/pool/detail/pool_construct.ipp
- copied unchanged from r73493, /trunk/boost/pool/detail/pool_construct.ipp
branches/release/boost/pool/detail/pool_construct_simple.ipp
- copied unchanged from r73493, /trunk/boost/pool/detail/pool_construct_simple.ipp
branches/release/libs/pool/doc/html/
- copied from r73493, /trunk/libs/pool/doc/html/
branches/release/libs/pool/doc/html/BOOST_POOL_VALIDATE_INTERNALS.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/BOOST_POOL_VALIDATE_INTERNALS.html
branches/release/libs/pool/doc/html/boost/
- copied from r73493, /trunk/libs/pool/doc/html/boost/
branches/release/libs/pool/doc/html/boost/default_user_allocator_malloc_free.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/default_user_allocator_malloc_free.html
branches/release/libs/pool/doc/html/boost/default_user_allocator_new_delete.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/default_user_allocator_new_delete.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator/
- copied from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator/
branches/release/libs/pool/doc/html/boost/fast_pool_allocator.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator/rebind.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator/rebind.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_tag.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_tag.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880/
- copied from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880/
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880/rebind.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id491880/rebind.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284/
- copied from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284/
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284.html
branches/release/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284/rebind.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/fast_pool_allocator_void__UserAllocat_id506284/rebind.html
branches/release/libs/pool/doc/html/boost/object_pool.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/object_pool.html
branches/release/libs/pool/doc/html/boost/pool.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool.html
branches/release/libs/pool/doc/html/boost/pool_allocator/
- copied from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator/
branches/release/libs/pool/doc/html/boost/pool_allocator.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator.html
branches/release/libs/pool/doc/html/boost/pool_allocator/rebind.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator/rebind.html
branches/release/libs/pool/doc/html/boost/pool_allocator_tag.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_tag.html
branches/release/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365/
- copied from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365/
branches/release/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365.html
branches/release/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365/rebind.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id491365/rebind.html
branches/release/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769/
- copied from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769/
branches/release/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769.html
branches/release/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769/rebind.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/pool_allocator_void__UserAllocator__M_id505769/rebind.html
branches/release/libs/pool/doc/html/boost/simple_segregated_storage.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/simple_segregated_storage.html
branches/release/libs/pool/doc/html/boost/singleton_pool/
- copied from r73493, /trunk/libs/pool/doc/html/boost/singleton_pool/
branches/release/libs/pool/doc/html/boost/singleton_pool.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/singleton_pool.html
branches/release/libs/pool/doc/html/boost/singleton_pool/object_creator.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost/singleton_pool/object_creator.html
branches/release/libs/pool/doc/html/boost_pool/
- copied from r73493, /trunk/libs/pool/doc/html/boost_pool/
branches/release/libs/pool/doc/html/boost_pool/appendices/
- copied from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/
branches/release/libs/pool/doc/html/boost_pool/appendices.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices.html
branches/release/libs/pool/doc/html/boost_pool/appendices/acknowledgements.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/acknowledgements.html
branches/release/libs/pool/doc/html/boost_pool/appendices/faq.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/faq.html
branches/release/libs/pool/doc/html/boost_pool/appendices/history.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/history.html
branches/release/libs/pool/doc/html/boost_pool/appendices/implementations.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/implementations.html
branches/release/libs/pool/doc/html/boost_pool/appendices/references.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/references.html
branches/release/libs/pool/doc/html/boost_pool/appendices/tests.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/tests.html
branches/release/libs/pool/doc/html/boost_pool/appendices/tickets.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/tickets.html
branches/release/libs/pool/doc/html/boost_pool/appendices/todo.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/appendices/todo.html
branches/release/libs/pool/doc/html/boost_pool/indexes/
- copied from r73493, /trunk/libs/pool/doc/html/boost_pool/indexes/
branches/release/libs/pool/doc/html/boost_pool/indexes.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/indexes.html
branches/release/libs/pool/doc/html/boost_pool/indexes/s01.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/indexes/s01.html
branches/release/libs/pool/doc/html/boost_pool/indexes/s02.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/indexes/s02.html
branches/release/libs/pool/doc/html/boost_pool/indexes/s03.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/indexes/s03.html
branches/release/libs/pool/doc/html/boost_pool/indexes/s04.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/indexes/s04.html
branches/release/libs/pool/doc/html/boost_pool/pool/
- copied from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/
branches/release/libs/pool/doc/html/boost_pool/pool.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool.html
branches/release/libs/pool/doc/html/boost_pool/pool/conventions.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/conventions.html
branches/release/libs/pool/doc/html/boost_pool/pool/installation.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/installation.html
branches/release/libs/pool/doc/html/boost_pool/pool/interfaces.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/interfaces.html
branches/release/libs/pool/doc/html/boost_pool/pool/introduction.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/introduction.html
branches/release/libs/pool/doc/html/boost_pool/pool/pooling.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/pooling.html
branches/release/libs/pool/doc/html/boost_pool/pool/testing.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/testing.html
branches/release/libs/pool/doc/html/boost_pool/pool/usage.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool/pool/usage.html
branches/release/libs/pool/doc/html/boost_pool_c___reference.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/boost_pool_c___reference.html
branches/release/libs/pool/doc/html/header/
- copied from r73493, /trunk/libs/pool/doc/html/header/
branches/release/libs/pool/doc/html/header/boost/
- copied from r73493, /trunk/libs/pool/doc/html/header/boost/
branches/release/libs/pool/doc/html/header/boost/pool/
- copied from r73493, /trunk/libs/pool/doc/html/header/boost/pool/
branches/release/libs/pool/doc/html/header/boost/pool/object_pool_hpp.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/header/boost/pool/object_pool_hpp.html
branches/release/libs/pool/doc/html/header/boost/pool/pool_alloc_hpp.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/header/boost/pool/pool_alloc_hpp.html
branches/release/libs/pool/doc/html/header/boost/pool/pool_hpp.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/header/boost/pool/pool_hpp.html
branches/release/libs/pool/doc/html/header/boost/pool/poolfwd_hpp.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/header/boost/pool/poolfwd_hpp.html
branches/release/libs/pool/doc/html/header/boost/pool/simple_segregated_storage_hpp.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/header/boost/pool/simple_segregated_storage_hpp.html
branches/release/libs/pool/doc/html/header/boost/pool/singleton_pool_hpp.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/header/boost/pool/singleton_pool_hpp.html
branches/release/libs/pool/doc/html/index.html
- copied unchanged from r73493, /trunk/libs/pool/doc/html/index.html
branches/release/libs/pool/doc/images/
- copied from r73493, /trunk/libs/pool/doc/images/
branches/release/libs/pool/doc/images/MB4.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/MB4.PNG
branches/release/libs/pool/doc/images/PC2.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/PC2.PNG
branches/release/libs/pool/doc/images/PC3.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/PC3.PNG
branches/release/libs/pool/doc/images/PC4.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/PC4.PNG
branches/release/libs/pool/doc/images/PC5.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/PC5.PNG
branches/release/libs/pool/doc/images/mb1.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb1.PNG
branches/release/libs/pool/doc/images/mb1.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb1.svg
branches/release/libs/pool/doc/images/mb2.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb2.PNG
branches/release/libs/pool/doc/images/mb2.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb2.svg
branches/release/libs/pool/doc/images/mb3.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb3.PNG
branches/release/libs/pool/doc/images/mb3.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb3.svg
branches/release/libs/pool/doc/images/mb4.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/mb4.svg
branches/release/libs/pool/doc/images/pc1.PNG
- copied unchanged from r73493, /trunk/libs/pool/doc/images/pc1.PNG
branches/release/libs/pool/doc/images/pc1.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/pc1.svg
branches/release/libs/pool/doc/images/pc2.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/pc2.svg
branches/release/libs/pool/doc/images/pc3.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/pc3.svg
branches/release/libs/pool/doc/images/pc4.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/pc4.svg
branches/release/libs/pool/doc/images/pc5.svg
- copied unchanged from r73493, /trunk/libs/pool/doc/images/pc5.svg
branches/release/libs/pool/doc/index.idx
- copied unchanged from r73493, /trunk/libs/pool/doc/index.idx
branches/release/libs/pool/doc/jamfile.v2
- copied unchanged from r73493, /trunk/libs/pool/doc/jamfile.v2
branches/release/libs/pool/doc/pool.pdf
- copied unchanged from r73493, /trunk/libs/pool/doc/pool.pdf
branches/release/libs/pool/doc/pool.qbk
- copied unchanged from r73493, /trunk/libs/pool/doc/pool.qbk
branches/release/libs/pool/example/
- copied from r73493, /trunk/libs/pool/example/
branches/release/libs/pool/example/sys_allocator.hpp
- copied unchanged from r73493, /trunk/libs/pool/example/sys_allocator.hpp
branches/release/libs/pool/example/time_pool_alloc.cpp
- copied unchanged from r73493, /trunk/libs/pool/example/time_pool_alloc.cpp
branches/release/libs/pool/test/test_bug_1252.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_bug_1252.cpp
branches/release/libs/pool/test/test_bug_2696.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_bug_2696.cpp
branches/release/libs/pool/test/test_bug_3349.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_bug_3349.cpp
branches/release/libs/pool/test/test_bug_4960.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_bug_4960.cpp
branches/release/libs/pool/test/test_bug_5526.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_bug_5526.cpp
branches/release/libs/pool/test/test_msvc_mem_leak_detect.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_msvc_mem_leak_detect.cpp
branches/release/libs/pool/test/test_poisoned_macros.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_poisoned_macros.cpp
branches/release/libs/pool/test/test_simple_seg_storage.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_simple_seg_storage.cpp
branches/release/libs/pool/test/test_simple_seg_storage.hpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_simple_seg_storage.hpp
branches/release/libs/pool/test/test_threading.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_threading.cpp
branches/release/libs/pool/test/test_valgrind_fail_1.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_valgrind_fail_1.cpp
branches/release/libs/pool/test/test_valgrind_fail_2.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/test_valgrind_fail_2.cpp
branches/release/libs/pool/test/track_allocator.hpp
- copied unchanged from r73493, /trunk/libs/pool/test/track_allocator.hpp
branches/release/libs/pool/test/valgrind_config_check.cpp
- copied unchanged from r73493, /trunk/libs/pool/test/valgrind_config_check.cpp
Removed:
branches/release/boost/pool/detail/ct_gcd_lcm.hpp
branches/release/boost/pool/detail/gcd_lcm.hpp
branches/release/boost/pool/detail/pool_construct.inc
branches/release/boost/pool/detail/pool_construct_simple.inc
branches/release/boost/pool/detail/singleton.hpp
branches/release/libs/pool/TODO.txt
branches/release/libs/pool/doc/concepts.html
branches/release/libs/pool/doc/implementation/
branches/release/libs/pool/doc/index.html
branches/release/libs/pool/doc/interfaces/
branches/release/libs/pool/doc/interfaces.html
branches/release/libs/pool/doc/pool.css
branches/release/libs/pool/test/sys_allocator.hpp
branches/release/libs/pool/test/time_pool_alloc.cpp
Properties modified:
branches/release/boost/pool/ (props changed)
branches/release/libs/pool/ (props changed)
Text files modified:
branches/release/boost/pool/detail/guard.hpp | 45 ++
branches/release/boost/pool/detail/mutex.hpp | 117 ------
branches/release/boost/pool/detail/pool_construct.bat | 6
branches/release/boost/pool/detail/pool_construct.sh | 3
branches/release/boost/pool/detail/pool_construct_simple.bat | 6
branches/release/boost/pool/detail/pool_construct_simple.sh | 3
branches/release/boost/pool/object_pool.hpp | 204 ++++++++++--
branches/release/boost/pool/pool.hpp | 660 ++++++++++++++++++++++++++++++++-------
branches/release/boost/pool/pool_alloc.hpp | 306 +++++++++++++++---
branches/release/boost/pool/poolfwd.hpp | 8
branches/release/boost/pool/simple_segregated_storage.hpp | 248 ++++++++++----
branches/release/boost/pool/singleton_pool.hpp | 239 +++++++++++---
branches/release/libs/pool/index.html | 6
branches/release/libs/pool/test/Jamfile.v2 | 57 +++
branches/release/libs/pool/test/test_pool_alloc.cpp | 501 +++++++++++++----------------
15 files changed, 1666 insertions(+), 743 deletions(-)
Deleted: branches/release/boost/pool/detail/ct_gcd_lcm.hpp
==============================================================================
--- branches/release/boost/pool/detail/ct_gcd_lcm.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,104 +0,0 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// 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_CT_GCD_LCM_HPP
-#define BOOST_POOL_CT_GCD_LCM_HPP
-
-#include <boost/static_assert.hpp>
-#include <boost/type_traits/ice.hpp>
-
-namespace boost {
-
-namespace details {
-namespace pool {
-
-// Compile-time calculation of greatest common divisor and least common multiple
-
-//
-// ct_gcd is a compile-time algorithm that calculates the greatest common
-// divisor of two unsigned integers, using Euclid's algorithm.
-//
-// assumes: A != 0 && B != 0
-//
-
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
-
-namespace details {
-template <unsigned A, unsigned B, bool Bis0>
-struct ct_gcd_helper;
-template <unsigned A, unsigned B>
-struct ct_gcd_helper<A, B, false>
-{
- BOOST_STATIC_CONSTANT(unsigned, A_mod_B_ = A % B);
- BOOST_STATIC_CONSTANT(unsigned, value =
- (::boost::details::pool::details::ct_gcd_helper<
- B, static_cast<unsigned>(A_mod_B_),
- ::boost::type_traits::ice_eq<A_mod_B_, 0>::value
- >::value) );
-};
-template <unsigned A, unsigned B>
-struct ct_gcd_helper<A, B, true>
-{
- BOOST_STATIC_CONSTANT(unsigned, value = A);
-};
-} // namespace details
-
-template <unsigned A, unsigned B>
-struct ct_gcd
-{
- BOOST_STATIC_ASSERT(A != 0 && B != 0);
- BOOST_STATIC_CONSTANT(unsigned, value =
- (::boost::details::pool::details::ct_gcd_helper<A, B, false>::value) );
-};
-
-#else
-
-// Thanks to Peter Dimov for providing this workaround!
-namespace details {
-template<unsigned A> struct ct_gcd2
-{
- template<unsigned B>
- struct helper
- {
- BOOST_STATIC_CONSTANT(unsigned, value = ct_gcd2<B>::helper<A % B>::value);
- };
- template<>
- struct helper<0>
- {
- BOOST_STATIC_CONSTANT(unsigned, value = A);
- };
-};
-} // namespace details
-
-template<unsigned A, unsigned B> struct ct_gcd
-{
- BOOST_STATIC_ASSERT(A != 0 && B != 0);
- enum { value = details::ct_gcd2<A>::helper<B>::value };
-};
-
-#endif
-
-//
-// ct_lcm is a compile-time algorithm that calculates the least common
-// multiple of two unsigned integers.
-//
-// assumes: A != 0 && B != 0
-//
-template <unsigned A, unsigned B>
-struct ct_lcm
-{
- BOOST_STATIC_CONSTANT(unsigned, value =
- (A / ::boost::details::pool::ct_gcd<A, B>::value * B) );
-};
-
-} // namespace pool
-} // namespace details
-
-} // namespace boost
-
-#endif
Deleted: branches/release/boost/pool/detail/gcd_lcm.hpp
==============================================================================
--- branches/release/boost/pool/detail/gcd_lcm.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,58 +0,0 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// 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_GCD_LCM_HPP
-#define BOOST_POOL_GCD_LCM_HPP
-
-namespace boost {
-
-namespace details {
-namespace pool {
-
-// Greatest common divisor and least common multiple
-
-//
-// gcd is an algorithm that calculates the greatest common divisor of two
-// integers, using Euclid's algorithm.
-//
-// Pre: A > 0 && B > 0
-// Recommended: A > B
-template <typename Integer>
-Integer gcd(Integer A, Integer B)
-{
- do
- {
- const Integer tmp(B);
- B = A % B;
- A = tmp;
- } while (B != 0);
-
- return A;
-}
-
-//
-// lcm is an algorithm that calculates the least common multiple of two
-// integers.
-//
-// Pre: A > 0 && B > 0
-// Recommended: A > B
-template <typename Integer>
-Integer lcm(const Integer & A, const Integer & B)
-{
- Integer ret = A;
- ret /= gcd(A, B);
- ret *= B;
- return ret;
-}
-
-} // namespace pool
-} // namespace details
-
-} // namespace boost
-
-#endif
Modified: branches/release/boost/pool/detail/guard.hpp
==============================================================================
--- branches/release/boost/pool/detail/guard.hpp (original)
+++ branches/release/boost/pool/detail/guard.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -9,28 +9,57 @@
#ifndef BOOST_POOL_GUARD_HPP
#define BOOST_POOL_GUARD_HPP
-// Extremely Light-Weight guard glass
+/*!
+ \file
+ \brief Extremely Light-Weight guard class.
+ \details Auto-lock/unlock-er
+ detail/guard.hpp provides a type guard<Mutex>
+ that allows scoped access to the Mutex's locking and unlocking operations.
+ It is used to ensure that a Mutex is unlocked, even if an exception is thrown.
+*/
namespace boost {
namespace details {
namespace pool {
-template <typename Mutex>
+template <typename Mutex> //!< \tparam Mutex (platform-specific) mutex class.
class guard
-{
+{ //! Locks the mutex, binding guard<Mutex> to Mutex.
+ /*! Example:
+ Given a (platform-specific) mutex class, we can wrap code as follows:
+
+ extern mutex global_lock;
+
+ static void f()
+ {
+ boost::details::pool::guard<mutex> g(global_lock);
+ // g's constructor locks "global_lock"
+
+ ... // do anything:
+ // throw exceptions
+ // return
+ // or just fall through
+ } // g's destructor unlocks "global_lock"
+ */
private:
Mutex & mtx;
- guard(const guard &);
+ guard(const guard &); //!< Guards the mutex, ensuring unlocked on destruction, even if exception is thrown.
void operator=(const guard &);
public:
explicit guard(Mutex & nmtx)
- :mtx(nmtx) { mtx.lock(); }
-
- ~guard() { mtx.unlock(); }
-};
+ :mtx(nmtx)
+ { //! Locks the mutex of the guard class.
+ mtx.lock();
+ }
+
+ ~guard()
+ { //! destructor unlocks the mutex of the guard class.
+ mtx.unlock();
+ }
+}; // class guard
} // namespace pool
} // namespace details
Modified: branches/release/boost/pool/detail/mutex.hpp
==============================================================================
--- branches/release/boost/pool/detail/mutex.hpp (original)
+++ branches/release/boost/pool/detail/mutex.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -10,108 +10,11 @@
#define BOOST_POOL_MUTEX_HPP
#include <boost/config.hpp> // for workarounds
-
-// Extremely Light-Weight wrapper classes for OS thread synchronization
-
-// Configuration: for now, we just choose between pthread or Win32 mutexes or none
-
-#define BOOST_MUTEX_HELPER_NONE 0
-#define BOOST_MUTEX_HELPER_WIN32 1
-#define BOOST_MUTEX_HELPER_PTHREAD 2
-
-#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
-# define BOOST_NO_MT
-#endif
-
-#ifdef BOOST_NO_MT
- // No multithreading -> make locks into no-ops
- #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
-#else
- #ifdef BOOST_WINDOWS
- #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
- #else
- #if defined(BOOST_HAS_UNISTD_H)
- #include <unistd.h>
- #endif
- #if defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS)
- #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
- #endif
- #endif
-#endif
-
-#ifndef BOOST_MUTEX_HELPER
- #error Unable to determine platform mutex type; define BOOST_NO_MT to assume single-threaded
-#endif
-
-#ifndef BOOST_NO_MT
-# ifdef BOOST_WINDOWS
-# include <windows.h>
-# endif
-# if defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS)
-# include <pthread.h>
-# endif
+#ifdef BOOST_HAS_THREADS
+#include <boost/thread/mutex.hpp>
#endif
-namespace boost {
-
-namespace details {
-namespace pool {
-
-#ifndef BOOST_NO_MT
-
-#ifdef BOOST_WINDOWS
-
-class win32_mutex
-{
- private:
- ::CRITICAL_SECTION mtx;
-
- win32_mutex(const win32_mutex &);
- void operator=(const win32_mutex &);
-
- public:
- win32_mutex()
- { ::InitializeCriticalSection(&mtx); }
-
- ~win32_mutex()
- { ::DeleteCriticalSection(&mtx); }
-
- void lock()
- { ::EnterCriticalSection(&mtx); }
-
- void unlock()
- { ::LeaveCriticalSection(&mtx); }
-};
-
-#endif // defined(BOOST_WINDOWS)
-
-#if defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS)
-
-class pthread_mutex
-{
- private:
- ::pthread_mutex_t mtx;
-
- pthread_mutex(const pthread_mutex &);
- void operator=(const pthread_mutex &);
-
- public:
- pthread_mutex()
- { ::pthread_mutex_init(&mtx, 0); }
-
- ~pthread_mutex()
- { ::pthread_mutex_destroy(&mtx); }
-
- void lock()
- { ::pthread_mutex_lock(&mtx); }
-
- void unlock()
- { ::pthread_mutex_unlock(&mtx); }
-};
-
-#endif // defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS)
-
-#endif // !defined(BOOST_NO_MT)
+namespace boost{ namespace details{ namespace pool{
class null_mutex
{
@@ -126,22 +29,14 @@
static void unlock() { }
};
-#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
+#if !defined(BOOST_HAS_THREADS) || defined(BOOST_NO_MT) || defined(BOOST_POOL_NO_MT)
typedef null_mutex default_mutex;
-#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
- typedef win32_mutex default_mutex;
-#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
- typedef pthread_mutex default_mutex;
+#else
+ typedef boost::mutex default_mutex;
#endif
} // namespace pool
} // namespace details
-
} // namespace boost
-#undef BOOST_MUTEX_HELPER_WIN32
-#undef BOOST_MUTEX_HELPER_PTHREAD
-#undef BOOST_MUTEX_HELPER_NONE
-#undef BOOST_MUTEX_HELPER
-
#endif
Modified: branches/release/boost/pool/detail/pool_construct.bat
==============================================================================
--- branches/release/boost/pool/detail/pool_construct.bat (original)
+++ branches/release/boost/pool/detail/pool_construct.bat 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -11,7 +11,7 @@
if %OS%==Windows_NT goto NT
rem Not NT - run m4 as normal, then exit
-m4 -P -E -DNumberOfArguments=%1 pool_construct.m4 > pool_construct.inc
+m4 -P -E -DNumberOfArguments=%1 pool_construct.m4 > pool_construct.ipp
goto end
rem DJGPP programs (including m4) running on Windows/NT do NOT support long
@@ -19,6 +19,6 @@
rem Note that the output doesn't have to be a short name because it's an
rem argument to the command shell, not m4.
:NT
-m4 -P -E -DNumberOfArguments=%1 < pool_construct.m4 > pool_construct.inc
+m4 -P -E -DNumberOfArguments=%1 < pool_construct.m4 > pool_construct.ipp
-:end
\ No newline at end of file
+:end
Deleted: branches/release/boost/pool/detail/pool_construct.inc
==============================================================================
--- branches/release/boost/pool/detail/pool_construct.inc 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,852 +0,0 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompany-
-// ing 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.
-
-// This file was AUTOMATICALLY GENERATED from "stdin"
-// Do NOT include directly!
-// Do NOT edit!
-
-template <typename T0>
-element_type * construct(T0 & a0)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0>
-element_type * construct(const T0 & a0)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0>
-element_type * construct(volatile T0 & a0)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0>
-element_type * construct(const volatile T0 & a0)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(T0 & a0, T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const T0 & a0, T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(volatile T0 & a0, T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const volatile T0 & a0, T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(T0 & a0, const T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const T0 & a0, const T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(volatile T0 & a0, const T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const volatile T0 & a0, const T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(T0 & a0, volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const T0 & a0, volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(volatile T0 & a0, volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const volatile T0 & a0, volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(T0 & a0, const volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const T0 & a0, const volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(volatile T0 & a0, const volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const volatile T0 & a0, const volatile T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const volatile T1 & a1, T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const volatile T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const volatile T1 & a1, volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(volatile T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const volatile T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-
Modified: branches/release/boost/pool/detail/pool_construct.sh
==============================================================================
--- branches/release/boost/pool/detail/pool_construct.sh (original)
+++ branches/release/boost/pool/detail/pool_construct.sh 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -8,4 +8,5 @@
# See http://www.boost.org for updates, documentation, and revision history.
#
-m4 -P -E -DNumberOfArguments=$1 pool_construct.m4 > pool_construct.inc
+m4 -P -E -DNumberOfArguments=$1 pool_construct.m4 > pool_construct.ipp
+
Modified: branches/release/boost/pool/detail/pool_construct_simple.bat
==============================================================================
--- branches/release/boost/pool/detail/pool_construct_simple.bat (original)
+++ branches/release/boost/pool/detail/pool_construct_simple.bat 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -12,7 +12,7 @@
if %OS%==Windows_NT goto NT
rem Not NT - run m4 as normal, then exit
-m4 -P -E -DNumberOfArguments=%1 pool_construct_simple.m4 > pool_construct_simple.inc
+m4 -P -E -DNumberOfArguments=%1 pool_construct_simple.m4 > pool_construct_simple.ipp
goto end
rem DJGPP programs (including m4) running on Windows/NT do NOT support long
@@ -20,6 +20,6 @@
rem Note that the output doesn't have to be a short name because it's an
rem argument to the command shell, not m4.
:NT
-m4 -P -E -DNumberOfArguments=%1 < pool_construct_simple.m4 > pool_construct_simple.inc
+m4 -P -E -DNumberOfArguments=%1 < pool_construct_simple.m4 > pool_construct_simple.ipp
-:end
\ No newline at end of file
+:end
Deleted: branches/release/boost/pool/detail/pool_construct_simple.inc
==============================================================================
--- branches/release/boost/pool/detail/pool_construct_simple.inc 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,43 +0,0 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// 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.
-
-// This file was AUTOMATICALLY GENERATED from "stdin"
-// Do NOT include directly!
-// Do NOT edit!
-
-template <typename T0>
-element_type * construct(const T0 & a0)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1>
-element_type * construct(const T0 & a0, const T1 & a1)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-template <typename T0, typename T1, typename T2>
-element_type * construct(const T0 & a0, const T1 & a1, const T2 & a2)
-{
- element_type * const ret = (malloc)();
- if (ret == 0)
- return ret;
- try { new (ret) element_type(a0, a1, a2); }
- catch (...) { (free)(ret); throw; }
- return ret;
-}
-
Modified: branches/release/boost/pool/detail/pool_construct_simple.sh
==============================================================================
--- branches/release/boost/pool/detail/pool_construct_simple.sh (original)
+++ branches/release/boost/pool/detail/pool_construct_simple.sh 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -8,4 +8,5 @@
# See http://www.boost.org for updates, documentation, and revision history.
#
-m4 -P -E -DNumberOfArguments=$1 pool_construct_simple.m4 > pool_construct_simple.inc
+m4 -P -E -DNumberOfArguments=$1 pool_construct_simple.m4 > pool_construct_simple.ipp
+
Deleted: branches/release/boost/pool/detail/singleton.hpp
==============================================================================
--- branches/release/boost/pool/detail/singleton.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,107 +0,0 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// 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_SINGLETON_HPP
-#define BOOST_POOL_SINGLETON_HPP
-
-// The following code might be put into some Boost.Config header in a later revision
-#ifdef __BORLANDC__
-# pragma option push -w-inl
-#endif
-
-//
-// The following helper classes are placeholders for a generic "singleton"
-// class. The classes below support usage of singletons, including use in
-// program startup/shutdown code, AS LONG AS there is only one thread
-// running before main() begins, and only one thread running after main()
-// exits.
-//
-// This class is also limited in that it can only provide singleton usage for
-// classes with default constructors.
-//
-
-// The design of this class is somewhat twisted, but can be followed by the
-// calling inheritance. Let us assume that there is some user code that
-// calls "singleton_default<T>::instance()". The following (convoluted)
-// sequence ensures that the same function will be called before main():
-// instance() contains a call to create_object.do_nothing()
-// Thus, object_creator is implicitly instantiated, and create_object
-// must exist.
-// Since create_object is a static member, its constructor must be
-// called before main().
-// The constructor contains a call to instance(), thus ensuring that
-// instance() will be called before main().
-// The first time instance() is called (i.e., before main()) is the
-// latest point in program execution where the object of type T
-// can be created.
-// Thus, any call to instance() will auto-magically result in a call to
-// instance() before main(), unless already present.
-// Furthermore, since the instance() function contains the object, instead
-// of the singleton_default class containing a static instance of the
-// object, that object is guaranteed to be constructed (at the latest) in
-// the first call to instance(). This permits calls to instance() from
-// static code, even if that code is called before the file-scope objects
-// in this file have been initialized.
-
-namespace boost {
-
-namespace details {
-namespace pool {
-
-// T must be: no-throw default constructible and no-throw destructible
-template <typename T>
-struct singleton_default
-{
- private:
- struct object_creator
- {
- // This constructor does nothing more than ensure that instance()
- // is called before main() begins, thus creating the static
- // T object before multithreading race issues can come up.
- object_creator() { singleton_default<T>::instance(); }
- inline void do_nothing() const { }
- };
- static object_creator create_object;
-
- singleton_default();
-
- public:
- typedef T object_type;
-
- // If, at any point (in user code), singleton_default<T>::instance()
- // is called, then the following function is instantiated.
- static object_type & instance()
- {
- // This is the object that we return a reference to.
- // It is guaranteed to be created before main() begins because of
- // the next line.
- static object_type obj;
-
- // The following line does nothing else than force the instantiation
- // of singleton_default<T>::create_object, whose constructor is
- // called before main() begins.
- create_object.do_nothing();
-
- return obj;
- }
-};
-template <typename T>
-typename singleton_default<T>::object_creator
-singleton_default<T>::create_object;
-
-} // namespace pool
-} // namespace details
-
-} // namespace boost
-
-// The following code might be put into some Boost.Config header in a later revision
-#ifdef __BORLANDC__
-# pragma option pop
-#endif
-
-#endif
Modified: branches/release/boost/pool/object_pool.hpp
==============================================================================
--- branches/release/boost/pool/object_pool.hpp (original)
+++ branches/release/boost/pool/object_pool.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -8,6 +8,12 @@
#ifndef BOOST_OBJECT_POOL_HPP
#define BOOST_OBJECT_POOL_HPP
+/*!
+\file
+\brief Provides a template type boost::object_pool<T, UserAllocator>
+that can be used for fast and efficient memory allocation of objects of type T.
+It also provides automatic destruction of non-deallocated objects.
+*/
#include <boost/pool/poolfwd.hpp>
@@ -33,41 +39,110 @@
namespace boost {
-// T must have a non-throwing destructor
+/*! \brief A template class
+that can be used for fast and efficient memory allocation of objects.
+It also provides automatic destruction of non-deallocated objects.
+
+\details
+
+<b>T</b> The type of object to allocate/deallocate.
+T must have a non-throwing destructor.
+
+<b>UserAllocator</b>
+Defines the allocator that the underlying Pool will use to allocate memory from the system.
+See User Allocators for details.
+
+Class object_pool is a template class
+that can be used for fast and efficient memory allocation of objects.
+It also provides automatic destruction of non-deallocated objects.
+
+When the object pool is destroyed, then the destructor for type T
+is called for each allocated T that has not yet been deallocated. O(N).
+
+Whenever an object of type ObjectPool needs memory from the system,
+it will request it from its UserAllocator template parameter.
+The amount requested is determined using a doubling algorithm;
+that is, each time more system memory is allocated,
+the amount of system memory requested is doubled.
+Users may control the doubling algorithm by the parameters passed
+to the object_pool's constructor.
+*/
+
template <typename T, typename UserAllocator>
class object_pool: protected pool<UserAllocator>
-{
+{ //!
public:
- typedef T element_type;
- typedef UserAllocator user_allocator;
- typedef typename pool<UserAllocator>::size_type size_type;
- typedef typename pool<UserAllocator>::difference_type difference_type;
+ typedef T element_type; //!< ElementType
+ typedef UserAllocator user_allocator; //!<
+ typedef typename pool<UserAllocator>::size_type size_type; //!< pool<UserAllocator>::size_type
+ typedef typename pool<UserAllocator>::difference_type difference_type; //!< pool<UserAllocator>::difference_type
protected:
- pool<UserAllocator> & store() { return *this; }
- const pool<UserAllocator> & store() const { return *this; }
+ //! \return The underlying boost:: \ref pool storage used by *this.
+ pool<UserAllocator> & store()
+ {
+ return *this;
+ }
+ //! \return The underlying boost:: \ref pool storage used by *this.
+ const pool<UserAllocator> & store() const
+ {
+ return *this;
+ }
// for the sake of code readability :)
static void * & nextof(void * const ptr)
- { return *(static_cast<void **>(ptr)); }
+ { //! \returns The next memory block after ptr (for the sake of code readability :)
+ return *(static_cast<void **>(ptr));
+ }
public:
- // This constructor parameter is an extension!
- explicit object_pool(const size_type next_size = 32, const size_type max_size = 0)
- :pool<UserAllocator>(sizeof(T), next_size, max_size) { }
+ explicit object_pool(const size_type arg_next_size = 32, const size_type arg_max_size = 0)
+ :
+ pool<UserAllocator>(sizeof(T), arg_next_size, arg_max_size)
+ { //! Constructs a new (empty by default) ObjectPool.
+ //! \param next_size Number of chunks to request from the system the next time that object needs to allocate system memory (default 32).
+ //! \pre next_size != 0.
+ //! \param max_size Maximum number of chunks to ever request from the system - this puts a cap on the doubling algorithm
+ //! used by the underlying pool.
+ }
~object_pool();
- // Returns 0 if out-of-memory
+ // Returns 0 if out-of-memory.
element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
- { return static_cast<element_type *>(store().ordered_malloc()); }
+ { //! Allocates memory that can hold one object of type ElementType.
+ //!
+ //! If out of memory, returns 0.
+ //!
+ //! Amortized O(1).
+ return static_cast<element_type *>(store().ordered_malloc());
+ }
void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)
- { store().ordered_free(chunk); }
+ { //! De-Allocates memory that holds a chunk of type ElementType.
+ //!
+ //! Note that p may not be 0.\n
+ //!
+ //! Note that the destructor for p is not called. O(N).
+ store().ordered_free(chunk);
+ }
bool is_from(element_type * const chunk) const
- { return store().is_from(chunk); }
+ { /*! \returns true if chunk was allocated from *this or
+ may be returned as the result of a future allocation from *this.
+
+ Returns false if chunk was allocated from some other pool or
+ may be returned as the result of a future allocation from some other pool.
+
+ Otherwise, the return value is meaningless.
+
+ \note This function may NOT be used to reliably test random pointer values!
+ */
+ return store().is_from(chunk);
+ }
element_type * construct()
- {
+ { //! \returns A pointer to an object of type T, allocated in memory from the underlying pool
+ //! and default constructed. The returned objected can be freed by a call to \ref destroy.
+ //! Otherwise the returned object will be automatically destroyed when *this is destroyed.
element_type * const ret = (malloc)();
if (ret == 0)
return ret;
@@ -76,29 +151,76 @@
return ret;
}
- // Include automatically-generated file for family of template construct()
- // functions
+
+#if defined(BOOST_DOXYGEN)
+ template <class Arg1, ... class ArgN>
+ element_type * construct(Arg1&, ... ArgN&)
+ {
+ //! \returns A pointer to an object of type T, allocated in memory from the underlying pool
+ //! and constructed from arguments Arg1 to ArgN. The returned objected can be freed by a call to \ref destroy.
+ //! Otherwise the returned object will be automatically destroyed when *this is destroyed.
+ //!
+ //! \note Since the number and type of arguments to this function is totally arbitrary, a simple system has been
+ //! set up to automatically generate template construct functions. This system is based on the macro preprocessor
+ //! m4, which is standard on UNIX systems and also available for Win32 systems.\n\n
+ //! detail/pool_construct.m4, when run with m4, will create the file detail/pool_construct.ipp, which only defines
+ //! the construct functions for the proper number of arguments. The number of arguments may be passed into the
+ //! file as an m4 macro, NumberOfArguments; if not provided, it will default to 3.\n\n
+ //! For each different number of arguments (1 to NumberOfArguments), a template function is generated. There
+ //! are the same number of template parameters as there are arguments, and each argument's type is a reference
+ //! to that (possibly cv-qualified) template argument. Each possible permutation of the cv-qualifications is also generated.\n\n
+ //! Because each permutation is generated for each possible number of arguments, the included file size grows
+ //! exponentially in terms of the number of constructor arguments, not linearly. For the sake of rational
+ //! compile times, only use as many arguments as you need.\n\n
+ //! detail/pool_construct.bat and detail/pool_construct.sh are also provided to call m4, defining NumberOfArguments
+ //! to be their command-line parameter. See these files for more details.
+ }
+#else
+// Include automatically-generated file for family of template construct() functions.
+// Copy .inc renamed .ipp to conform to Doxygen include filename expectations, PAB 12 Jan 11.
+// But still get Doxygen warning:
+// I:/boost-sandbox/guild/pool/boost/pool/object_pool.hpp:82:
+// Warning: include file boost/pool/detail/pool_construct.ipp
+// not found, perhaps you forgot to add its directory to INCLUDE_PATH?
+// But the file IS found and referenced OK, but cannot view code.
+// This seems because not at the head of the file
+// But if moved this up, Doxygen is happy, but of course it won't compile,
+// because the many constructors *must* go here.
+
#ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
-# include <boost/pool/detail/pool_construct.inc>
+# include <boost/pool/detail/pool_construct.ipp>
#else
-# include <boost/pool/detail/pool_construct_simple.inc>
+# include <boost/pool/detail/pool_construct_simple.ipp>
+#endif
#endif
-
void destroy(element_type * const chunk)
- {
+ { //! Destroys an object allocated with \ref construct.
+ //!
+ //! Equivalent to:
+ //!
+ //! p->~ElementType(); this->free(p);
+ //!
+ //! \pre p must have been previously allocated from *this via a call to \ref construct.
chunk->~T();
(free)(chunk);
}
- // These functions are extensions!
- size_type get_next_size() const { return store().get_next_size(); }
- void set_next_size(const size_type x) { store().set_next_size(x); }
+ size_type get_next_size() const
+ { //! \returns The number of chunks that will be allocated next time we run out of memory.
+ return store().get_next_size();
+ }
+ void set_next_size(const size_type x)
+ { //! Set a new number of chunks to allocate the next time we run out of memory.
+ //! \param x wanted next_size (must not be zero).
+ store().set_next_size(x);
+ }
};
template <typename T, typename UserAllocator>
object_pool<T, UserAllocator>::~object_pool()
{
- // handle trivial case
+#ifndef BOOST_POOL_VALGRIND
+ // handle trivial case of invalid list.
if (!this->list.valid())
return;
@@ -115,36 +237,44 @@
// increment next
next = next.next();
- // delete all contained objects that aren't freed
+ // delete all contained objects that aren't freed.
- // Iterate 'i' through all chunks in the memory block
+ // Iterate 'i' through all chunks in the memory block.
for (char * i = iter.begin(); i != iter.end(); i += partition_size)
{
- // If this chunk is free
+ // If this chunk is free,
if (i == freed_iter)
{
- // Increment freed_iter to point to next in free list
+ // Increment freed_iter to point to next in free list.
freed_iter = nextof(freed_iter);
- // Continue searching chunks in the memory block
+ // Continue searching chunks in the memory block.
continue;
}
- // This chunk is not free (allocated), so call its destructor
+ // This chunk is not free (allocated), so call its destructor,
static_cast<T *>(static_cast<void *>(i))->~T();
- // and continue searching chunks in the memory block
+ // and continue searching chunks in the memory block.
}
- // free storage
+ // free storage.
(UserAllocator::free)(iter.begin());
- // increment iter
+ // increment iter.
iter = next;
} while (iter.valid());
// Make the block list empty so that the inherited destructor doesn't try to
- // free it again.
+ // free it again.
this->list.invalidate();
+#else
+ // destruct all used elements:
+ for(std::set<void*>::iterator pos = this->used_list.begin(); pos != this->used_list.end(); ++pos)
+ {
+ static_cast<T*>(*pos)->~T();
+ }
+ // base class will actually free the memory...
+#endif
}
} // namespace boost
Modified: branches/release/boost/pool/pool.hpp
==============================================================================
--- branches/release/boost/pool/pool.hpp (original)
+++ branches/release/boost/pool/pool.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -26,12 +26,23 @@
#include <boost/pool/poolfwd.hpp>
-// boost::details::pool::ct_lcm
-#include <boost/pool/detail/ct_gcd_lcm.hpp>
-// boost::details::pool::lcm
-#include <boost/pool/detail/gcd_lcm.hpp>
+// boost::math::static_lcm
+#include <boost/math/common_factor_ct.hpp>
// boost::simple_segregated_storage
#include <boost/pool/simple_segregated_storage.hpp>
+// boost::alignment_of
+#include <boost/type_traits/alignment_of.hpp>
+// BOOST_ASSERT
+#include <boost/assert.hpp>
+
+#ifdef BOOST_POOL_INSTRUMENT
+#include <iostream>
+#include<iomanip>
+#endif
+#ifdef BOOST_POOL_VALGRIND
+#include <set>
+#include <valgrind/memcheck.h>
+#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::malloc; using ::free; }
@@ -44,41 +55,99 @@
// parameter.
// Thanks to Jens Maurer for pointing this out!
-namespace boost {
+/*!
+ \file
+ \brief Provides class \ref pool: a fast memory allocator that guarantees proper alignment of all allocated chunks,
+ and which extends and generalizes the framework provided by the simple segregated storage solution.
+ Also provides two UserAllocator classes which can be used in conjuction with \ref pool.
+*/
+
+/*!
+ \mainpage Boost.Pool Memory Allocation Scheme
+
+ \section intro_sec Introduction
+
+ Pool allocation is a memory allocation scheme that is very fast, but limited in its usage.
+
+ This Doxygen-style documentation is complementary to the
+ full Quickbook-generated html and pdf documentation at www.boost.org.
+
+ This page generated from file pool.hpp.
+
+*/
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127) // Conditional expression is constant
+#endif
+
+ namespace boost
+{
+
+//! \brief Allocator used as the default template parameter for
+//! a UserAllocator
+//! template parameter. Uses new and delete.
struct default_user_allocator_new_delete
{
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type; //!< An unsigned integral type that can represent the size of the largest object to be allocated.
+ typedef std::ptrdiff_t difference_type; //!< A signed integral type that can represent the difference of any two pointers.
static char * malloc BOOST_PREVENT_MACRO_SUBSTITUTION(const size_type bytes)
- { return new (std::nothrow) char[bytes]; }
+ { //! Attempts to allocate n bytes from the system. Returns 0 if out-of-memory
+ return new (std::nothrow) char[bytes];
+ }
static void free BOOST_PREVENT_MACRO_SUBSTITUTION(char * const block)
- { delete [] block; }
+ { //! Attempts to de-allocate block.
+ //! \pre Block must have been previously returned from a call to UserAllocator::malloc.
+ delete [] block;
+ }
};
+//! \brief UserAllocator
+//! used as template parameter for \ref pool and \ref object_pool.
+//! Uses malloc and free internally.
struct default_user_allocator_malloc_free
{
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type; //!< An unsigned integral type that can represent the size of the largest object to be allocated.
+ typedef std::ptrdiff_t difference_type; //!< A signed integral type that can represent the difference of any two pointers.
static char * malloc BOOST_PREVENT_MACRO_SUBSTITUTION(const size_type bytes)
- { return static_cast<char *>(std::malloc(bytes)); }
+ { return static_cast<char *>((std::malloc)(bytes)); }
static void free BOOST_PREVENT_MACRO_SUBSTITUTION(char * const block)
- { std::free(block); }
+ { (std::free)(block); }
};
-namespace details {
+namespace details
+{ //! Implemention only.
-// PODptr is a class that pretends to be a "pointer" to different class types
-// that don't really exist. It provides member functions to access the "data"
-// of the "object" it points to. Since these "class" types are of variable
-// size, and contains some information at the *end* of its memory (for
-// alignment reasons), PODptr must contain the size of this "class" as well as
-// the pointer to this "object".
template <typename SizeType>
class PODptr
-{
+{ //! PODptr is a class that pretends to be a "pointer" to different class types
+ //! that don't really exist. It provides member functions to access the "data"
+ //! of the "object" it points to. Since these "class" types are of variable
+ //! size, and contains some information at the *end* of its memory
+ //! (for alignment reasons),
+ //! PODptr must contain the size of this "class" as well as the pointer to this "object".
+
+ /*! \details A PODptr holds the location and size of a memory block allocated from the system.
+ Each memory block is split logically into three sections:
+
+ <b>Chunk area</b>. This section may be different sizes. PODptr does not care what the size of the chunks is,
+ but it does care (and keep track of) the total size of the chunk area.
+
+ <b>Next pointer</b>. This section is always the same size for a given SizeType. It holds a pointer
+ to the location of the next memory block in the memory block list, or 0 if there is no such block.
+
+ <b>Next size</b>. This section is always the same size for a given SizeType. It holds the size of the
+ next memory block in the memory block list.
+
+The PODptr class just provides cleaner ways of dealing with raw memory blocks.
+
+A PODptr object is either valid or invalid. An invalid PODptr is analogous to a null pointer.
+The default constructor for PODptr will result in an invalid object.
+Calling the member function invalidate will result in that object becoming invalid.
+The member function valid can be used to test for validity.
+*/
public:
typedef SizeType size_type;
@@ -87,84 +156,178 @@
size_type sz;
char * ptr_next_size() const
- { return (ptr + sz - sizeof(size_type)); }
+ {
+ return (ptr + sz - sizeof(size_type));
+ }
char * ptr_next_ptr() const
{
return (ptr_next_size() -
- pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value);
}
public:
PODptr(char * const nptr, const size_type nsize)
- :ptr(nptr), sz(nsize) { }
+ :ptr(nptr), sz(nsize)
+ {
+ //! A PODptr may be created to point to a memory block by passing
+ //! the address and size of that memory block into the constructor.
+ //! A PODptr constructed in this way is valid.
+ }
PODptr()
- :ptr(0), sz(0) { }
+ : ptr(0), sz(0)
+ { //! default constructor for PODptr will result in an invalid object.
+ }
- bool valid() const { return (begin() != 0); }
- void invalidate() { begin() = 0; }
- char * & begin() { return ptr; }
- char * begin() const { return ptr; }
- char * end() const { return ptr_next_ptr(); }
- size_type total_size() const { return sz; }
+ bool valid() const
+ { //! A PODptr object is either valid or invalid.
+ //! An invalid PODptr is analogous to a null pointer.
+ //! \returns true if PODptr is valid, false if invalid.
+ return (begin() != 0);
+ }
+ void invalidate()
+ { //! Make object invalid.
+ begin() = 0;
+ }
+ char * & begin()
+ { //! Each PODptr keeps the address and size of its memory block.
+ //! \returns The address of its memory block.
+ return ptr;
+ }
+ char * begin() const
+ { //! Each PODptr keeps the address and size of its memory block.
+ //! \return The address of its memory block.
+ return ptr;
+ }
+ char * end() const
+ { //! \returns begin() plus element_size (a 'past the end' value).
+ return ptr_next_ptr();
+ }
+ size_type total_size() const
+ { //! Each PODptr keeps the address and size of its memory block.
+ //! The address may be read or written by the member functions begin.
+ //! The size of the memory block may only be read,
+ //! \returns size of the memory block.
+ return sz;
+ }
size_type element_size() const
- {
- return (sz - sizeof(size_type) -
- pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);
+ { //! \returns size of element pointer area.
+ return static_cast<size_type>(sz - sizeof(size_type) -
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value);
}
size_type & next_size() const
- {
+ { //!
+ //! \returns next_size.
return *(static_cast<size_type *>(static_cast<void*>((ptr_next_size()))));
}
char * & next_ptr() const
- { return *(static_cast<char **>(static_cast<void*>(ptr_next_ptr()))); }
+ { //! \returns pointer to next pointer area.
+ return *(static_cast<char **>(static_cast<void*>(ptr_next_ptr())));
+ }
PODptr next() const
- { return PODptr<size_type>(next_ptr(), next_size()); }
+ { //! \returns next PODptr.
+ return PODptr<size_type>(next_ptr(), next_size());
+ }
void next(const PODptr & arg) const
- {
+ { //! Sets next PODptr.
next_ptr() = arg.begin();
next_size() = arg.total_size();
}
-};
-
+}; // class PODptr
} // namespace details
+#ifndef BOOST_POOL_VALGRIND
+/*!
+ \brief A fast memory allocator that guarantees proper alignment of all allocated chunks.
+
+ \details Whenever an object of type pool needs memory from the system,
+ it will request it from its UserAllocator template parameter.
+ The amount requested is determined using a doubling algorithm;
+ that is, each time more system memory is allocated,
+ the amount of system memory requested is doubled.
+
+ Users may control the doubling algorithm by using the following extensions:
+
+ Users may pass an additional constructor parameter to pool.
+ This parameter is of type size_type,
+ and is the number of chunks to request from the system
+ the first time that object needs to allocate system memory.
+ The default is 32. This parameter may not be 0.
+
+ Users may also pass an optional third parameter to pool's
+ constructor. This parameter is of type size_type,
+ and sets a maximum size for allocated chunks. When this
+ parameter takes the default value of 0, then there is no upper
+ limit on chunk size.
+
+ Finally, if the doubling algorithm results in no memory
+ being allocated, the pool will backtrack just once, halving
+ the chunk size and trying again.
+
+ <b>UserAllocator type</b> - the method that the Pool will use to allocate memory from the system.
+
+ There are essentially two ways to use class pool: the client can call \ref malloc() and \ref free() to allocate
+ and free single chunks of memory, this is the most efficient way to use a pool, but does not allow for
+ the efficient allocation of arrays of chunks. Alternatively, the client may call \ref ordered_malloc() and \ref
+ ordered_free(), in which case the free list is maintained in an ordered state, and efficient allocation of arrays
+ of chunks are possible. However, this latter option can suffer from poor performance when large numbers of
+ allocations are performed.
+
+*/
template <typename UserAllocator>
-class pool: protected simple_segregated_storage<
- typename UserAllocator::size_type>
+class pool: protected simple_segregated_storage < typename UserAllocator::size_type >
{
public:
- typedef UserAllocator user_allocator;
- typedef typename UserAllocator::size_type size_type;
- typedef typename UserAllocator::difference_type difference_type;
+ typedef UserAllocator user_allocator; //!< User allocator.
+ typedef typename UserAllocator::size_type size_type; //!< An unsigned integral type that can represent the size of the largest object to be allocated.
+ typedef typename UserAllocator::difference_type difference_type; //!< A signed integral type that can represent the difference of any two pointers.
private:
- BOOST_STATIC_CONSTANT(unsigned, min_alloc_size =
- (::boost::details::pool::ct_lcm<sizeof(void *), sizeof(size_type)>::value) );
-
- // Returns 0 if out-of-memory
- // Called if malloc/ordered_malloc needs to resize the free list
- void * malloc_need_resize();
- void * ordered_malloc_need_resize();
+ BOOST_STATIC_CONSTANT(size_type, min_alloc_size =
+ (::boost::math::static_lcm<sizeof(void *), sizeof(size_type)>::value) );
+ BOOST_STATIC_CONSTANT(size_type, min_align =
+ (::boost::math::static_lcm< ::boost::alignment_of<void *>::value, ::boost::alignment_of<size_type>::value>::value) );
+
+ //! \returns 0 if out-of-memory.
+ //! Called if malloc/ordered_malloc needs to resize the free list.
+ void * malloc_need_resize(); //! Called if malloc needs to resize the free list.
+ void * ordered_malloc_need_resize(); //! Called if ordered_malloc needs to resize the free list.
protected:
- details::PODptr<size_type> list;
+ details::PODptr<size_type> list; //!< List structure holding ordered blocks.
- simple_segregated_storage<size_type> & store() { return *this; }
- const simple_segregated_storage<size_type> & store() const { return *this; }
+ simple_segregated_storage<size_type> & store()
+ { //! \returns pointer to store.
+ return *this;
+ }
+ const simple_segregated_storage<size_type> & store() const
+ { //! \returns pointer to store.
+ return *this;
+ }
const size_type requested_size;
size_type next_size;
size_type start_size;
size_type max_size;
- // finds which POD in the list 'chunk' was allocated from
+ //! finds which POD in the list 'chunk' was allocated from.
details::PODptr<size_type> find_POD(void * const chunk) const;
- // is_from() tests a chunk to determine if it belongs in a block
+ // is_from() tests a chunk to determine if it belongs in a block.
static bool is_from(void * const chunk, char * const i,
const size_type sizeof_i)
- {
+ { //! \param chunk chunk to check if is from this pool.
+ //! \param i memory chunk at i with element sizeof_i.
+ //! \param sizeof_i element size (size of the chunk area of that block, not the total size of that block).
+ //! \returns true if chunk was allocated or may be returned.
+ //! as the result of a future allocation.
+ //!
+ //! Returns false if chunk was allocated from some other pool,
+ //! or may be returned as the result of a future allocation from some other pool.
+ //! Otherwise, the return value is meaningless.
+ //!
+ //! Note that this function may not be used to reliably test random pointer values.
+
// We use std::less_equal and std::less to test 'chunk'
// against the array bounds because standard operators
// may return unspecified results.
@@ -172,35 +335,52 @@
// defined for pointers to objects that are 1) in the same array, or
// 2) subobjects of the same object [5.9/2].
// The functor objects guarantee a total order for any pointer [20.3.3/8]
-//WAS:
-// return (std::less_equal<void *>()(static_cast<void *>(i), chunk)
-// && std::less<void *>()(chunk,
-// static_cast<void *>(i + sizeof_i)));
std::less_equal<void *> lt_eq;
std::less<void *> lt;
return (lt_eq(i, chunk) && lt(chunk, i + sizeof_i));
}
size_type alloc_size() const
- {
- const unsigned min_size = min_alloc_size;
- return details::pool::lcm<size_type>(requested_size, min_size);
+ { //! Calculated size of the memory chunks that will be allocated by this Pool.
+ //! \returns allocated size.
+ // For alignment reasons, this used to be defined to be lcm(requested_size, sizeof(void *), sizeof(size_type)),
+ // but is now more parsimonious: just rounding up to the minimum required alignment of our housekeeping data
+ // when required. This works provided all alignments are powers of two.
+ size_type s = (std::max)(requested_size, min_alloc_size);
+ size_type rem = s % min_align;
+ if(rem)
+ s += min_align - rem;
+ BOOST_ASSERT(s >= min_alloc_size);
+ BOOST_ASSERT(s % min_align == 0);
+ return s;
}
- // for the sake of code readability :)
static void * & nextof(void * const ptr)
- { return *(static_cast<void **>(ptr)); }
+ { //! \returns Pointer dereferenced.
+ //! (Provided and used for the sake of code readability :)
+ return *(static_cast<void **>(ptr));
+ }
public:
- // The second parameter here is an extension!
// pre: npartition_size != 0 && nnext_size != 0
explicit pool(const size_type nrequested_size,
const size_type nnext_size = 32,
const size_type nmax_size = 0)
- :list(0, 0), requested_size(nrequested_size), next_size(nnext_size), start_size(nnext_size),max_size(nmax_size)
- { }
+ :
+ list(0, 0), requested_size(nrequested_size), next_size(nnext_size), start_size(nnext_size),max_size(nmax_size)
+ { //! Constructs a new empty Pool that can be used to allocate chunks of size RequestedSize.
+ //! \param nrequested_size Requested chunk size
+ //! \param nnext_size parameter is of type size_type,
+ //! is the number of chunks to request from the system
+ //! the first time that object needs to allocate system memory.
+ //! The default is 32. This parameter may not be 0.
+ //! \param nmax_size is the maximum number of chunks to allocate in one block.
+ }
- ~pool() { purge_memory(); }
+ ~pool()
+ { //! Destructs the Pool, freeing its list of memory blocks.
+ purge_memory();
+ }
// Releases memory blocks that don't have chunks allocated
// pre: lists are ordered
@@ -211,19 +391,40 @@
// Returns true if memory was actually deallocated
bool purge_memory();
- // These functions are extensions!
- size_type get_next_size() const { return next_size; }
- void set_next_size(const size_type nnext_size) { next_size = start_size = nnext_size; }
- size_type get_max_size() const { return max_size; }
- void set_max_size(const size_type nmax_size) { max_size = nmax_size; }
- size_type get_requested_size() const { return requested_size; }
+ size_type get_next_size() const
+ { //! Number of chunks to request from the system the next time that object needs to allocate system memory. This value should never be 0.
+ //! \returns next_size;
+ return next_size;
+ }
+ void set_next_size(const size_type nnext_size)
+ { //! Set number of chunks to request from the system the next time that object needs to allocate system memory. This value should never be set to 0.
+ //! \returns nnext_size.
+ next_size = start_size = nnext_size;
+ }
+ size_type get_max_size() const
+ { //! \returns max_size.
+ return max_size;
+ }
+ void set_max_size(const size_type nmax_size)
+ { //! Set max_size.
+ max_size = nmax_size;
+ }
+ size_type get_requested_size() const
+ { //! \returns the requested size passed into the constructor.
+ //! (This value will not change during the lifetime of a Pool object).
+ return requested_size;
+ }
// Both malloc and ordered_malloc do a quick inlined check first for any
// free chunks. Only if we need to get another memory block do we call
// the non-inlined *_need_resize() functions.
// Returns 0 if out-of-memory
void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
- {
+ { //! Allocates a chunk of memory. Searches in the list of memory blocks
+ //! for a block that has a free chunk, and returns that free chunk if found.
+ //! Otherwise, creates a new memory block, adds its free list to pool's free list,
+ //! \returns a free chunk from that block.
+ //! If a new memory block cannot be allocated, returns 0. Amortized O(1).
// Look for a non-empty storage
if (!store().empty())
return (store().malloc)();
@@ -231,7 +432,9 @@
}
void * ordered_malloc()
- {
+ { //! Same as malloc, only merges the free lists, to preserve order. Amortized O(1).
+ //! \returns a free chunk from that block.
+ //! If a new memory block cannot be allocated, returns 0. Amortized O(1).
// Look for a non-empty storage
if (!store().empty())
return (store().malloc)();
@@ -241,21 +444,42 @@
// Returns 0 if out-of-memory
// Allocate a contiguous section of n chunks
void * ordered_malloc(size_type n);
+ //! Same as malloc, only allocates enough contiguous chunks to cover n * requested_size bytes. Amortized O(n).
+ //! \returns a free chunk from that block.
+ //! If a new memory block cannot be allocated, returns 0. Amortized O(1).
// pre: 'chunk' must have been previously
// returned by *this.malloc().
void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const chunk)
- { (store().free)(chunk); }
+ { //! Deallocates a chunk of memory. Note that chunk may not be 0. O(1).
+ //!
+ //! Chunk must have been previously returned by t.malloc() or t.ordered_malloc().
+ //! Assumes that chunk actually refers to a block of chunks
+ //! spanning n * partition_sz bytes.
+ //! deallocates each chunk in that block.
+ //! Note that chunk may not be 0. O(n).
+ (store().free)(chunk);
+ }
// pre: 'chunk' must have been previously
// returned by *this.malloc().
void ordered_free(void * const chunk)
- { store().ordered_free(chunk); }
+ { //! Same as above, but is order-preserving.
+ //!
+ //! Note that chunk may not be 0. O(N) with respect to the size of the free list.
+ //! chunk must have been previously returned by t.malloc() or t.ordered_malloc().
+ store().ordered_free(chunk);
+ }
// pre: 'chunk' must have been previously
// returned by *this.malloc(n).
void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const chunks, const size_type n)
- {
+ { //! Assumes that chunk actually refers to a block of chunks.
+ //!
+ //! chunk must have been previously returned by t.ordered_malloc(n)
+ //! spanning n * partition_sz bytes.
+ //! Deallocates each chunk in that block.
+ //! Note that chunk may not be 0. O(n).
const size_type partition_size = alloc_size();
const size_type total_req_size = n * requested_size;
const size_type num_chunks = total_req_size / partition_size +
@@ -267,7 +491,12 @@
// pre: 'chunk' must have been previously
// returned by *this.malloc(n).
void ordered_free(void * const chunks, const size_type n)
- {
+ { //! Assumes that chunk actually refers to a block of chunks spanning n * partition_sz bytes;
+ //! deallocates each chunk in that block.
+ //!
+ //! Note that chunk may not be 0. Order-preserving. O(N + n) where N is the size of the free list.
+ //! chunk must have been previously returned by t.malloc() or t.ordered_malloc().
+
const size_type partition_size = alloc_size();
const size_type total_req_size = n * requested_size;
const size_type num_chunks = total_req_size / partition_size +
@@ -278,15 +507,29 @@
// is_from() tests a chunk to determine if it was allocated from *this
bool is_from(void * const chunk) const
- {
+ { //! \returns Returns true if chunk was allocated from u or
+ //! may be returned as the result of a future allocation from u.
+ //! Returns false if chunk was allocated from some other pool or
+ //! may be returned as the result of a future allocation from some other pool.
+ //! Otherwise, the return value is meaningless.
+ //! Note that this function may not be used to reliably test random pointer values.
return (find_POD(chunk).valid());
}
};
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+template <typename UserAllocator>
+typename pool<UserAllocator>::size_type const pool<UserAllocator>::min_alloc_size;
+template <typename UserAllocator>
+typename pool<UserAllocator>::size_type const pool<UserAllocator>::min_align;
+#endif
+
template <typename UserAllocator>
bool pool<UserAllocator>::release_memory()
-{
- // This is the return value: it will be set to true when we actually call
+{ //! pool must be ordered. Frees every memory block that doesn't have any allocated chunks.
+ //! \returns true if at least one memory block was freed.
+
+ // ret is the return value: it will be set to true when we actually call
// UserAllocator::free(..)
bool ret = false;
@@ -371,7 +614,7 @@
// free_p points to the first free chunk in some next memory block, or
// 0 if there is no such chunk.
// prev_free_p points to the last free chunk in this memory block.
-
+
// We are just about to advance ptr. Maintain the invariant:
// prev is the PODptr whose next() is ptr, or !valid()
// if there is no such PODptr
@@ -408,7 +651,13 @@
template <typename UserAllocator>
bool pool<UserAllocator>::purge_memory()
-{
+{ //! pool must be ordered.
+ //! Frees every memory block.
+ //!
+ //! This function invalidates any pointers previously returned
+ //! by allocation functions of t.
+ //! \returns true if at least one memory block was freed.
+
details::PODptr<size_type> iter = list;
if (!iter.valid())
@@ -435,16 +684,28 @@
template <typename UserAllocator>
void * pool<UserAllocator>::malloc_need_resize()
-{
- // No memory in any of our storages; make a new storage,
- const size_type partition_size = alloc_size();
- const size_type POD_size = next_size * partition_size +
- details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
- char * const ptr = (UserAllocator::malloc)(POD_size);
+{ //! No memory in any of our storages; make a new storage,
+ //! Allocates chunk in newly malloc aftert resize.
+ //! \returns pointer to chunk.
+ size_type partition_size = alloc_size();
+ size_type POD_size = static_cast<size_type>(next_size * partition_size +
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
+ char * ptr = (UserAllocator::malloc)(POD_size);
if (ptr == 0)
- return 0;
+ {
+ if(next_size > 4)
+ {
+ next_size >>= 1;
+ partition_size = alloc_size();
+ POD_size = static_cast<size_type>(next_size * partition_size +
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
+ ptr = (UserAllocator::malloc)(POD_size);
+ }
+ if(ptr == 0)
+ return 0;
+ }
const details::PODptr<size_type> node(ptr, POD_size);
-
+
BOOST_USING_STD_MIN();
if(!max_size)
next_size <<= 1;
@@ -464,14 +725,25 @@
template <typename UserAllocator>
void * pool<UserAllocator>::ordered_malloc_need_resize()
-{
- // No memory in any of our storages; make a new storage,
- const size_type partition_size = alloc_size();
- const size_type POD_size = next_size * partition_size +
- details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
- char * const ptr = (UserAllocator::malloc)(POD_size);
+{ //! No memory in any of our storages; make a new storage,
+ //! \returns pointer to new chunk.
+ size_type partition_size = alloc_size();
+ size_type POD_size = static_cast<size_type>(next_size * partition_size +
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
+ char * ptr = (UserAllocator::malloc)(POD_size);
if (ptr == 0)
- return 0;
+ {
+ if(next_size > 4)
+ {
+ next_size >>= 1;
+ partition_size = alloc_size();
+ POD_size = static_cast<size_type>(next_size * partition_size +
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
+ ptr = (UserAllocator::malloc)(POD_size);
+ }
+ if(ptr == 0)
+ return 0;
+ }
const details::PODptr<size_type> node(ptr, POD_size);
BOOST_USING_STD_MIN();
@@ -511,14 +783,16 @@
node.next(prev.next());
prev.next(node);
}
-
// and return a chunk from it.
return (store().malloc)();
}
template <typename UserAllocator>
void * pool<UserAllocator>::ordered_malloc(const size_type n)
-{
+{ //! Gets address of a chunk n, allocating new memory if not already available.
+ //! \returns Address of chunk n if allocated ok.
+ //! \returns 0 if not enough memory for n chunks.
+
const size_type partition_size = alloc_size();
const size_type total_req_size = n * requested_size;
const size_type num_chunks = total_req_size / partition_size +
@@ -526,23 +800,40 @@
void * ret = store().malloc_n(num_chunks, partition_size);
- if (ret != 0)
+#ifdef BOOST_POOL_INSTRUMENT
+ std::cout << "Allocating " << n << " chunks from pool of size " << partition_size << std::endl;
+#endif
+ if ((ret != 0) || (n == 0))
return ret;
- // Not enougn memory in our storages; make a new storage,
+#ifdef BOOST_POOL_INSTRUMENT
+ std::cout << "Cache miss, allocating another chunk...\n";
+#endif
+
+ // Not enough memory in our storages; make a new storage,
BOOST_USING_STD_MAX();
next_size = max BOOST_PREVENT_MACRO_SUBSTITUTION(next_size, num_chunks);
- const size_type POD_size = next_size * partition_size +
- details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
- char * const ptr = (UserAllocator::malloc)(POD_size);
+ size_type POD_size = static_cast<size_type>(next_size * partition_size +
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
+ char * ptr = (UserAllocator::malloc)(POD_size);
if (ptr == 0)
- return 0;
+ {
+ if(num_chunks < next_size)
+ {
+ // Try again with just enough memory to do the job, or at least whatever we
+ // allocated last time:
+ next_size >>= 1;
+ next_size = max BOOST_PREVENT_MACRO_SUBSTITUTION(next_size, num_chunks);
+ POD_size = static_cast<size_type>(next_size * partition_size +
+ math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
+ ptr = (UserAllocator::malloc)(POD_size);
+ }
+ if(ptr == 0)
+ return 0;
+ }
const details::PODptr<size_type> node(ptr, POD_size);
- // Split up block so we can use what wasn't requested
- // (we can use "add_block" here because we know that
- // the free list is empty, so we don't have to use
- // the slower ordered version)
+ // Split up block so we can use what wasn't requested.
if (next_size > num_chunks)
store().add_ordered_block(node.begin() + num_chunks * partition_size,
node.element_size() - num_chunks * partition_size, partition_size);
@@ -554,7 +845,7 @@
next_size = min BOOST_PREVENT_MACRO_SUBSTITUTION(next_size << 1, max_size*requested_size/ partition_size);
// insert it into the list,
- // handle border case
+ // handle border case.
if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
{
node.next(list);
@@ -566,8 +857,7 @@
while (true)
{
- // if we're about to hit the end or
- // if we've found where "node" goes
+ // if we're about to hit the end, or if we've found where "node" goes.
if (prev.next_ptr() == 0
|| std::greater<void *>()(prev.next_ptr(), node.begin()))
break;
@@ -586,8 +876,9 @@
template <typename UserAllocator>
details::PODptr<typename pool<UserAllocator>::size_type>
pool<UserAllocator>::find_POD(void * const chunk) const
-{
- // We have to find which storage this chunk is from.
+{ //! find which PODptr storage memory that this chunk is from.
+ //! \returns the PODptr that holds this chunk.
+ // Iterate down list to find which storage this chunk is from.
details::PODptr<size_type> iter = list;
while (iter.valid())
{
@@ -599,6 +890,135 @@
return iter;
}
+#else // BOOST_POOL_VALGRIND
+
+template<typename UserAllocator>
+class pool
+{
+public:
+ // types
+ typedef UserAllocator user_allocator; // User allocator.
+ typedef typename UserAllocator::size_type size_type; // An unsigned integral type that can represent the size of the largest object to be allocated.
+ typedef typename UserAllocator::difference_type difference_type; // A signed integral type that can represent the difference of any two pointers.
+
+ // construct/copy/destruct
+ explicit pool(const size_type s, const size_type = 32, const size_type m = 0) : chunk_size(s), max_alloc_size(m) {}
+ ~pool()
+ {
+ purge_memory();
+ }
+
+ bool release_memory()
+ {
+ bool ret = free_list.empty() ? false : true;
+ for(std::set<void*>::iterator pos = free_list.begin(); pos != free_list.end(); ++pos)
+ {
+ (user_allocator::free)(static_cast<char*>(*pos));
+ }
+ free_list.clear();
+ return ret;
+ }
+ bool purge_memory()
+ {
+ bool ret = free_list.empty() && used_list.empty() ? false : true;
+ for(std::set<void*>::iterator pos = free_list.begin(); pos != free_list.end(); ++pos)
+ {
+ (user_allocator::free)(static_cast<char*>(*pos));
+ }
+ free_list.clear();
+ for(std::set<void*>::iterator pos = used_list.begin(); pos != used_list.end(); ++pos)
+ {
+ (user_allocator::free)(static_cast<char*>(*pos));
+ }
+ used_list.clear();
+ return ret;
+ }
+ size_type get_next_size() const
+ {
+ return 1;
+ }
+ void set_next_size(const size_type){}
+ size_type get_max_size() const
+ {
+ return max_alloc_size;
+ }
+ void set_max_size(const size_type s)
+ {
+ max_alloc_size = s;
+ }
+ size_type get_requested_size() const
+ {
+ return chunk_size;
+ }
+ void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
+ {
+ void* ret;
+ if(free_list.empty())
+ {
+ ret = (user_allocator::malloc)(chunk_size);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, chunk_size);
+ }
+ else
+ {
+ ret = *free_list.begin();
+ free_list.erase(free_list.begin());
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, chunk_size);
+ }
+ used_list.insert(ret);
+ return ret;
+ }
+ void * ordered_malloc()
+ {
+ return (this->malloc)();
+ }
+ void * ordered_malloc(size_type n)
+ {
+ if(max_alloc_size && (n > max_alloc_size))
+ return 0;
+ void* ret = (user_allocator::malloc)(chunk_size * n);
+ used_list.insert(ret);
+ return ret;
+ }
+ void free BOOST_PREVENT_MACRO_SUBSTITUTION(void *const chunk)
+ {
+ BOOST_ASSERT(used_list.count(chunk) == 1);
+ BOOST_ASSERT(free_list.count(chunk) == 0);
+ used_list.erase(chunk);
+ free_list.insert(chunk);
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, chunk_size);
+ }
+ void ordered_free(void *const chunk)
+ {
+ return (this->free)(chunk);
+ }
+ void free BOOST_PREVENT_MACRO_SUBSTITUTION(void *const chunk, const size_type)
+ {
+ BOOST_ASSERT(used_list.count(chunk) == 1);
+ BOOST_ASSERT(free_list.count(chunk) == 0);
+ used_list.erase(chunk);
+ (user_allocator::free)(static_cast<char*>(chunk));
+ }
+ void ordered_free(void *const chunk, const size_type n)
+ {
+ (this->free)(chunk, n);
+ }
+ bool is_from(void *const chunk) const
+ {
+ return used_list.count(chunk) || free_list.count(chunk);
+ }
+
+protected:
+ size_type chunk_size, max_alloc_size;
+ std::set<void*> free_list, used_list;
+};
+
+#endif
+
} // namespace boost
+#ifdef BOOST_MSVC
+#pragma warning(pop)
#endif
+
+#endif // #ifdef BOOST_POOL_HPP
+
Modified: branches/release/boost/pool/pool_alloc.hpp
==============================================================================
--- branches/release/boost/pool/pool_alloc.hpp (original)
+++ branches/release/boost/pool/pool_alloc.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -1,4 +1,5 @@
// 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
@@ -9,6 +10,62 @@
#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
@@ -22,6 +79,11 @@
#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))
@@ -30,57 +92,108 @@
namespace boost {
-struct pool_allocator_tag { };
+#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
+ User Allocators 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>
+ unsigned MaxSize >
class pool_allocator
{
public:
- typedef T value_type;
- typedef UserAllocator user_allocator;
- typedef Mutex mutex;
- BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
+ 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 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;
+ { //
+ typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
};
public:
pool_allocator()
- {
- // Required to ensure construction of singleton_pool IFF an
- // instace of this allocator is constructed during global
- // initialization. See ticket #2359 for a complete explaination
- // ( http://svn.boost.org/trac/boost/ticket/2359 )
+ { /*! 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 copy constructor.
- // default assignment operator
+ // default assignment operator.
// not explicit, mimicking std::allocator [20.4.1]
template <typename U>
pool_allocator(const pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> &)
- {
- // Required to ensure construction of singleton_pool IFF an
- // instace of this allocator is constructed during global
- // initialization. See ticket #2359 for a complete explaination
- // ( http://svn.boost.org/trac/boost/ticket/2359 )
+ { /*! 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);
}
@@ -98,7 +211,7 @@
static void destroy(const pointer ptr)
{
ptr->~T();
- (void) ptr; // avoid unused variable warning
+ (void) ptr; // avoid unused variable warning.
}
bool operator==(const pool_allocator &) const
@@ -108,17 +221,33 @@
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)
+ if ((ret == 0) && n)
boost::throw_exception(std::bad_alloc());
return ret;
}
static pointer allocate(const size_type n, const void * const)
- { return allocate(n); }
+ { //! 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;
@@ -128,6 +257,10 @@
}
};
+/*! \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,
@@ -139,18 +272,64 @@
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
- template <class U> struct rebind {
- typedef pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize> other;
+ //! \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;
};
};
-struct fast_pool_allocator_tag { };
+//! 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 User Allocators 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>
+ unsigned MaxSize >
class fast_pool_allocator
{
public:
@@ -166,6 +345,12 @@
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
{
@@ -175,35 +360,37 @@
public:
fast_pool_allocator()
{
- // Required to ensure construction of singleton_pool IFF an
- // instace of this allocator is constructed during global
- // initialization. See ticket #2359 for a complete explaination
- // ( http://svn.boost.org/trac/boost/ticket/2359 )
+ //! 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
- // default assignment operator
+ // Default copy constructor used.
- // not explicit, mimicking std::allocator [20.4.1]
+ // 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> &)
{
- // Required to ensure construction of singleton_pool IFF an
- // instace of this allocator is constructed during global
- // initialization. See ticket #2359 for a complete explaination
- // ( http://svn.boost.org/trac/boost/ticket/2359 )
+ //! 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
+ // Default destructor used.
static pointer address(reference r)
- { return &r; }
+ {
+ return &r;
+ }
static const_pointer address(const_reference s)
{ return &s; }
static size_type max_size()
@@ -211,9 +398,9 @@
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
+ (void) ptr; // Avoid unused variable warning.
}
bool operator==(const fast_pool_allocator &) const
@@ -223,7 +410,7 @@
static pointer allocate(const size_type n)
{
- const pointer ret = (n == 1) ?
+ const pointer ret = (n == 1) ?
static_cast<pointer>(
(singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize, MaxSize>::malloc)() ) :
@@ -235,9 +422,11 @@
return ret;
}
static pointer allocate(const size_type n, const void * const)
- { return allocate(n); }
+ { //! 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)() );
@@ -246,7 +435,8 @@
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;
@@ -259,24 +449,36 @@
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>
+ unsigned MaxSize >
class fast_pool_allocator<void, UserAllocator, Mutex, NextSize, MaxSize>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
- template <class U> struct rebind {
+
+ //! \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;
};
};
Modified: branches/release/boost/pool/poolfwd.hpp
==============================================================================
--- branches/release/boost/pool/poolfwd.hpp (original)
+++ branches/release/boost/pool/poolfwd.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -9,6 +9,12 @@
#ifndef BOOST_POOLFWD_HPP
#define BOOST_POOLFWD_HPP
+/*!
+ \file
+ \brief Forward declarations of all public (non-implemention) classes.
+*/
+
+
#include <boost/config.hpp> // for workarounds
// std::size_t
@@ -48,7 +54,7 @@
typename Mutex = details::pool::default_mutex,
unsigned NextSize = 32,
unsigned MaxSize = 0>
-struct singleton_pool;
+class singleton_pool;
//
// Location: <boost/pool/pool_alloc.hpp>
Modified: branches/release/boost/pool/simple_segregated_storage.hpp
==============================================================================
--- branches/release/boost/pool/simple_segregated_storage.hpp (original)
+++ branches/release/boost/pool/simple_segregated_storage.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -9,13 +9,55 @@
#ifndef BOOST_SIMPLE_SEGREGATED_STORAGE_HPP
#define BOOST_SIMPLE_SEGREGATED_STORAGE_HPP
+/*!
+ \file
+ \brief Simple Segregated Storage.
+ \details A simple segregated storage implementation:
+ simple segregated storage is the basic idea behind the Boost Pool library.
+ Simple segregated storage is the simplest, and probably the fastest,
+ memory allocation/deallocation algorithm.
+ It begins by partitioning a memory block into fixed-size chunks.
+ Where the block comes from is not important until implementation time.
+ A Pool is some object that uses Simple Segregated Storage in this fashion.
+*/
+
// std::greater
#include <functional>
#include <boost/pool/poolfwd.hpp>
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127) // Conditional expression is constant
+#endif
+
+#ifdef BOOST_POOL_VALIDATE
+# define BOOST_POOL_VALIDATE_INTERNALS validate();
+#else
+# define BOOST_POOL_VALIDATE_INTERNALS
+#endif
+
namespace boost {
+/*!
+
+\brief Simple Segregated Storage is the simplest, and probably the fastest,
+memory allocation/deallocation algorithm. It is responsible for
+partitioning a memory block into fixed-size chunks: where the block comes from
+is determined by the client of the class.
+
+\details Template class simple_segregated_storage controls access to a free list of memory chunks.
+Please note that this is a very simple class, with preconditions on almost all its functions. It is intended to
+be the fastest and smallest possible quick memory allocator - e.g., something to use in embedded systems.
+This class delegates many difficult preconditions to the user (i.e., alignment issues).
+
+An object of type simple_segregated_storage<SizeType> is empty if its free list is empty.
+If it is not empty, then it is ordered if its free list is ordered. A free list is ordered if repeated calls
+to <tt>malloc()</tt> will result in a constantly-increasing sequence of values, as determined by <tt>std::less<void *></tt>.
+A member function is <i>order-preserving</i> if the free list maintains its order orientation (that is, an
+ordered free list is still ordered after the member function call).
+
+*/
template <typename SizeType>
class simple_segregated_storage
{
@@ -26,38 +68,37 @@
simple_segregated_storage(const simple_segregated_storage &);
void operator=(const simple_segregated_storage &);
- // pre: (n > 0), (start != 0), (nextof(start) != 0)
- // post: (start != 0)
static void * try_malloc_n(void * & start, size_type n,
size_type partition_size);
protected:
- void * first;
+ void * first; /*!< This data member is the free list.
+ It points to the first chunk in the free list,
+ or is equal to 0 if the free list is empty.
+ */
- // Traverses the free list referred to by "first",
- // and returns the iterator previous to where
- // "ptr" would go if it was in the free list.
- // Returns 0 if "ptr" would go at the beginning
- // of the free list (i.e., before "first")
void * find_prev(void * ptr);
// for the sake of code readability :)
static void * & nextof(void * const ptr)
- { return *(static_cast<void **>(ptr)); }
+ { //! The return value is just *ptr cast to the appropriate type. ptr must not be 0. (For the sake of code readability :)
+ //! As an example, let us assume that we want to truncate the free list after the first chunk.
+ //! That is, we want to set *first to 0; this will result in a free list with only one entry.
+ //! The normal way to do this is to first cast first to a pointer to a pointer to void,
+ //! and then dereference and assign (*static_cast<void **>(first) = 0;).
+ //! This can be done more easily through the use of this convenience function (nextof(first) = 0;).
+ //! \returns dereferenced pointer.
+ return *(static_cast<void **>(ptr));
+ }
public:
// Post: empty()
simple_segregated_storage()
- :first(0) { }
+ :first(0)
+ { //! Construct empty storage area.
+ //! \post empty()
+ }
- // pre: npartition_sz >= sizeof(void *)
- // npartition_sz = sizeof(void *) * i, for some integer i
- // nsz >= npartition_sz
- // block is properly aligned for an array of object of
- // size npartition_sz and array of void *
- // The requirements above guarantee that any pointer to a chunk
- // (which is a pointer to an element in an array of npartition_sz)
- // may be cast to void **.
static void * segregate(void * block,
size_type nsz, size_type npartition_sz,
void * end = 0);
@@ -66,21 +107,25 @@
// Post: !empty()
void add_block(void * const block,
const size_type nsz, const size_type npartition_sz)
- {
- // Segregate this block and merge its free list into the
- // free list referred to by "first"
+ { //! Add block
+ //! Segregate this block and merge its free list into the
+ //! free list referred to by "first".
+ //! \pre Same as segregate.
+ //! \post !empty()
+ BOOST_POOL_VALIDATE_INTERNALS
first = segregate(block, nsz, npartition_sz, first);
+ BOOST_POOL_VALIDATE_INTERNALS
}
// Same preconditions as 'segregate'
// Post: !empty()
void add_ordered_block(void * const block,
const size_type nsz, const size_type npartition_sz)
- {
- // This (slower) version of add_block segregates the
- // block and merges its free list into our free list
- // in the proper order
-
+ { //! add block (ordered into list)
+ //! This (slower) version of add_block segregates the
+ //! block and merges its free list into our free list
+ //! in the proper order.
+ BOOST_POOL_VALIDATE_INTERNALS
// Find where "block" would go in the free list
void * const loc = find_prev(block);
@@ -89,43 +134,50 @@
add_block(block, nsz, npartition_sz);
else
nextof(loc) = segregate(block, nsz, npartition_sz, nextof(loc));
+ BOOST_POOL_VALIDATE_INTERNALS
}
- // default destructor
+ // default destructor.
- bool empty() const { return (first == 0); }
+ bool empty() const
+ { //! \returns true only if simple_segregated_storage is empty.
+ return (first == 0);
+ }
- // pre: !empty()
void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
- {
+ { //! Create a chunk.
+ //! \pre !empty()
+ //! Increment the "first" pointer to point to the next chunk.
+ BOOST_POOL_VALIDATE_INTERNALS
void * const ret = first;
- // Increment the "first" pointer to point to the next chunk
+ // Increment the "first" pointer to point to the next chunk.
first = nextof(first);
+ BOOST_POOL_VALIDATE_INTERNALS
return ret;
}
- // pre: chunk was previously returned from a malloc() referring to the
- // same free list
- // post: !empty()
void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const chunk)
- {
+ { //! Free a chunk.
+ //! \pre chunk was previously returned from a malloc() referring to the same free list.
+ //! \post !empty()
+ BOOST_POOL_VALIDATE_INTERNALS
nextof(chunk) = first;
first = chunk;
+ BOOST_POOL_VALIDATE_INTERNALS
}
- // pre: chunk was previously returned from a malloc() referring to the
- // same free list
- // post: !empty()
void ordered_free(void * const chunk)
- {
- // This (slower) implementation of 'free' places the memory
- // back in the list in its proper order.
+ { //! This (slower) implementation of 'free' places the memory
+ //! back in the list in its proper order.
+ //! \pre chunk was previously returned from a malloc() referring to the same free list
+ //! \post !empty().
// Find where "chunk" goes in the free list
+ BOOST_POOL_VALIDATE_INTERNALS
void * const loc = find_prev(chunk);
- // Place either at beginning or in middle/end
+ // Place either at beginning or in middle/end.
if (loc == 0)
(free)(chunk);
else
@@ -133,47 +185,81 @@
nextof(chunk) = nextof(loc);
nextof(loc) = chunk;
}
+ BOOST_POOL_VALIDATE_INTERNALS
}
- // Note: if you're allocating/deallocating n a lot, you should
- // be using an ordered pool.
- void * malloc_n(size_type n, size_type partition_size);
-
- // pre: chunks was previously allocated from *this with the same
- // values for n and partition_size
- // post: !empty()
- // Note: if you're allocating/deallocating n a lot, you should
- // be using an ordered pool.
+ void * malloc_n(size_type n, size_type partition_size);
+
+ //! \pre chunks was previously allocated from *this with the same
+ //! values for n and partition_size.
+ //! \post !empty()
+ //! \note If you're allocating/deallocating n a lot, you should
+ //! be using an ordered pool.
void free_n(void * const chunks, const size_type n,
const size_type partition_size)
- {
+ {
+ BOOST_POOL_VALIDATE_INTERNALS
if(n != 0)
add_block(chunks, n * partition_size, partition_size);
+ BOOST_POOL_VALIDATE_INTERNALS
}
// pre: chunks was previously allocated from *this with the same
- // values for n and partition_size
+ // values for n and partition_size.
// post: !empty()
void ordered_free_n(void * const chunks, const size_type n,
const size_type partition_size)
- {
+ { //! Free n chunks from order list.
+ //! \pre chunks was previously allocated from *this with the same
+ //! values for n and partition_size.
+
+ //! \pre n should not be zero (n == 0 has no effect).
+ BOOST_POOL_VALIDATE_INTERNALS
if(n != 0)
add_ordered_block(chunks, n * partition_size, partition_size);
+ BOOST_POOL_VALIDATE_INTERNALS
+ }
+#ifdef BOOST_POOL_VALIDATE
+ void validate()
+ {
+ int index = 0;
+ void* old = 0;
+ void* ptr = first;
+ while(ptr)
+ {
+ void* pt = nextof(ptr); // trigger possible segfault *before* we update variables
+ ++index;
+ old = ptr;
+ ptr = nextof(ptr);
+ }
}
+#endif
};
+//! Traverses the free list referred to by "first",
+//! and returns the iterator previous to where
+//! "ptr" would go if it was in the free list.
+//! Returns 0 if "ptr" would go at the beginning
+//! of the free list (i.e., before "first").
+
+//! \note Note that this function finds the location previous to where ptr would go
+//! if it was in the free list.
+//! It does not find the entry in the free list before ptr
+//! (unless ptr is already in the free list).
+//! Specifically, find_prev(0) will return 0,
+//! not the last entry in the free list.
+//! \returns location previous to where ptr would go if it was in the free list.
template <typename SizeType>
void * simple_segregated_storage<SizeType>::find_prev(void * const ptr)
-{
- // Handle border case
+{
+ // Handle border case.
if (first == 0 || std::greater<void *>()(first, ptr))
return 0;
void * iter = first;
while (true)
{
- // if we're about to hit the end or
- // if we've found where "ptr" goes
+ // if we're about to hit the end, or if we've found where "ptr" goes.
if (nextof(iter) == 0 || std::greater<void *>()(nextof(iter), ptr))
return iter;
@@ -181,6 +267,15 @@
}
}
+//! Segregate block into chunks.
+//! \pre npartition_sz >= sizeof(void *)
+//! \pre npartition_sz = sizeof(void *) * i, for some integer i
+//! \pre nsz >= npartition_sz
+//! \pre Block is properly aligned for an array of object of
+//! size npartition_sz and array of void *.
+//! The requirements above guarantee that any pointer to a chunk
+//! (which is a pointer to an element in an array of npartition_sz)
+//! may be cast to void **.
template <typename SizeType>
void * simple_segregated_storage<SizeType>::segregate(
void * const block,
@@ -214,18 +309,20 @@
return block;
}
-// The following function attempts to find n contiguous chunks
-// of size partition_size in the free list, starting at start.
-// If it succeds, it returns the last chunk in that contiguous
-// sequence, so that the sequence is known by [start, {retval}]
-// If it fails, it does do either because it's at the end of the
-// free list or hits a non-contiguous chunk. In either case,
-// it will return 0, and set start to the last considered
-// chunk. You are at the end of the free list if
-// nextof(start) == 0. Otherwise, start points to the last
-// chunk in the contiguous sequence, and nextof(start) points
-// to the first chunk in the next contiguous sequence (assuming
-// an ordered free list)
+//! \pre (n > 0), (start != 0), (nextof(start) != 0)
+//! \post (start != 0)
+//! The function attempts to find n contiguous chunks
+//! of size partition_size in the free list, starting at start.
+//! If it succeds, it returns the last chunk in that contiguous
+//! sequence, so that the sequence is known by [start, {retval}]
+//! If it fails, it does do either because it's at the end of the
+//! free list or hits a non-contiguous chunk. In either case,
+//! it will return 0, and set start to the last considered
+//! chunk. You are at the end of the free list if
+//! nextof(start) == 0. Otherwise, start points to the last
+//! chunk in the contiguous sequence, and nextof(start) points
+//! to the first chunk in the next contiguous sequence (assuming
+//! an ordered free list).
template <typename SizeType>
void * simple_segregated_storage<SizeType>::try_malloc_n(
void * & start, size_type n, const size_type partition_size)
@@ -245,10 +342,16 @@
return iter;
}
+//! Attempts to find a contiguous sequence of n partition_sz-sized chunks. If found, removes them
+//! all from the free list and returns a pointer to the first. If not found, returns 0. It is strongly
+//! recommended (but not required) that the free list be ordered, as this algorithm will fail to find
+//! a contiguous sequence unless it is contiguous in the free list as well. Order-preserving.
+//! O(N) with respect to the size of the free list.
template <typename SizeType>
void * simple_segregated_storage<SizeType>::malloc_n(const size_type n,
const size_type partition_size)
{
+ BOOST_POOL_VALIDATE_INTERNALS
if(n == 0)
return 0;
void * start = &first;
@@ -261,9 +364,14 @@
} while (iter == 0);
void * const ret = nextof(start);
nextof(start) = nextof(iter);
+ BOOST_POOL_VALIDATE_INTERNALS
return ret;
}
} // namespace boost
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
#endif
Modified: branches/release/boost/pool/singleton_pool.hpp
==============================================================================
--- branches/release/boost/pool/singleton_pool.hpp (original)
+++ branches/release/boost/pool/singleton_pool.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -9,111 +9,242 @@
#ifndef BOOST_SINGLETON_POOL_HPP
#define BOOST_SINGLETON_POOL_HPP
+/*!
+ \file
+ \brief The <tt>singleton_pool</tt> class allows other pool interfaces
+ for types of the same size to share the same underlying pool.
+
+ \details Header singleton_pool.hpp provides a template class <tt>singleton_pool</tt>,
+ which provides access to a pool as a singleton object.
+
+*/
+
#include <boost/pool/poolfwd.hpp>
// boost::pool
#include <boost/pool/pool.hpp>
-// boost::details::pool::singleton_default
-#include <boost/pool/detail/singleton.hpp>
// boost::details::pool::guard
#include <boost/pool/detail/guard.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+
namespace boost {
-//
-// The singleton_pool class allows other pool interfaces for types of the same
-// size to share the same pool
-//
-template <typename Tag, unsigned RequestedSize,
+ /*!
+ The singleton_pool class allows other pool interfaces
+ for types of the same size to share the same pool. Template
+ parameters are as follows:
+
+ <b>Tag</b> User-specified type to uniquely identify this pool: allows different unbounded sets of singleton pools to exist.
+
+ <b>RequestedSize</b> The size of each chunk returned by member function <tt>malloc()</tt>.
+
+ <B>UserAllocator</b> User allocator, default = default_user_allocator_new_delete.
+
+ <b>Mutex</B> This class is the type of mutex to use to protect simultaneous access to the underlying Pool.
+ Can be any Boost.Thread Mutex type or <tt>boost::details::pool::null_mutex</tt>.
+ It is exposed so that users may declare some singleton pools normally (i.e., with synchronization), but
+ some singleton pools without synchronization (by specifying <tt>boost::details::pool::null_mutex</tt>) for efficiency reasons.
+ The member typedef <tt>mutex</tt> exposes the value of this template parameter. The default for this
+ parameter is boost::details::pool::default_mutex which is a synonym for either <tt>boost::details::pool::null_mutex</tt>
+ (when threading support is turned off in the compiler (so BOOST_HAS_THREADS is not set), or threading support
+ has ben explicitly disabled with BOOST_DISABLE_THREADS (Boost-wide disabling of threads) or BOOST_POOL_NO_MT (this library only))
+ or for <tt>boost::mutex</tt> (when threading support is enabled in the compiler).
+
+ <B>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created and
+ specifies the number of chunks to allocate in the first allocation request (defaults to 32).
+ The member typedef <tt>static const value next_size</tt> exposes the value of this template parameter.
+
+ <b>MaxSize</B>The value of this parameter is passed to the underlying Pool when it is created and
+ specifies the maximum number of chunks to allocate in any single allocation request (defaults to 0).
+
+ <b>Notes:</b>
+
+ The underlying pool <i>p</i> referenced by the static functions
+ in singleton_pool is actually declared in a way that is:
+
+ 1 Thread-safe if there is only one thread running before main() begins and after main() ends
+ -- all of the static functions of singleton_pool synchronize their access to p.
+
+ 2 Guaranteed to be constructed before it is used --
+ thus, the simple static object in the synopsis above would actually be an incorrect implementation.
+ The actual implementation to guarantee this is considerably more complicated.
+
+ 3 Note too that a different underlying pool p exists
+ for each different set of template parameters,
+ including implementation-specific ones.
+
+ 4 The underlying pool is constructed "as if" by:
+
+ pool<UserAllocator> p(RequestedSize, NextSize, MaxSize);
+
+ \attention
+ The underlying pool constructed by the singleton
+ <b>is never freed</b>. This means that memory allocated
+ by a singleton_pool can be still used after main() has
+ completed, but may mean that some memory checking programs
+ will complain about leaks from singleton_pool.
+
+ */
+
+ template <typename Tag,
+ unsigned RequestedSize,
typename UserAllocator,
typename Mutex,
unsigned NextSize,
- unsigned MaxSize>
-struct singleton_pool
+ unsigned MaxSize >
+class singleton_pool
{
public:
- typedef Tag tag;
- typedef Mutex mutex;
- typedef UserAllocator user_allocator;
- typedef typename pool<UserAllocator>::size_type size_type;
- typedef typename pool<UserAllocator>::difference_type difference_type;
+ typedef Tag tag; /*!< The Tag template parameter uniquely
+ identifies this pool and allows
+ different unbounded sets of singleton pools to exist.
+ For example, the pool allocators use two tag classes to ensure that the
+ two different allocator types never share the same underlying singleton pool.
+ Tag is never actually used by singleton_pool.
+ */
+ typedef Mutex mutex; //!< The type of mutex used to synchonise access to this pool (default <tt>details::pool::default_mutex</tt>).
+ typedef UserAllocator user_allocator; //!< The user-allocator used by this pool, default = <tt>default_user_allocator_new_delete</tt>.
+ typedef typename pool<UserAllocator>::size_type size_type; //!< size_type of user allocator.
+ typedef typename pool<UserAllocator>::difference_type difference_type; //!< difference_type of user allocator.
- BOOST_STATIC_CONSTANT(unsigned, requested_size = RequestedSize);
- BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
+ BOOST_STATIC_CONSTANT(unsigned, requested_size = RequestedSize); //!< The size of each chunk allocated by this pool.
+ BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< The number of chunks to allocate on the first allocation.
- private:
- struct pool_type: Mutex
+private:
+ singleton_pool();
+
+#ifndef BOOST_DOXYGEN
+ struct pool_type: public Mutex, public pool<UserAllocator>
{
- pool<UserAllocator> p;
- pool_type():p(RequestedSize, NextSize) { }
- };
+ pool_type() : pool<UserAllocator>(RequestedSize, NextSize, MaxSize) {}
+ }; // struct pool_type: Mutex
- typedef details::pool::singleton_default<pool_type> singleton;
+#else
+ //
+ // This is invoked when we build with Doxygen only:
+ //
+public:
+ static pool<UserAllocator> p; //!< For exposition only!
+#endif
- singleton_pool();
public:
static void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.malloc(); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- return (p.p.malloc)();
+ return (p.malloc)();
}
static void * ordered_malloc()
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.ordered_malloc(); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- return p.p.ordered_malloc();
+ return p.ordered_malloc();
}
static void * ordered_malloc(const size_type n)
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.ordered_malloc(n); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- return p.p.ordered_malloc(n);
+ return p.ordered_malloc(n);
}
static bool is_from(void * const ptr)
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.is_from(chunk); synchronized.
+ //! \returns true if chunk is from SingletonPool::is_from(chunk)
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- return p.p.is_from(ptr);
+ return p.is_from(ptr);
}
static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr)
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.free(chunk); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- (p.p.free)(ptr);
+ (p.free)(ptr);
}
static void ordered_free(void * const ptr)
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.ordered_free(chunk); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- p.p.ordered_free(ptr);
+ p.ordered_free(ptr);
}
static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr, const size_type n)
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.free(chunk, n); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- (p.p.free)(ptr, n);
+ (p.free)(ptr, n);
}
static void ordered_free(void * const ptr, const size_type n)
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.ordered_free(chunk, n); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- p.p.ordered_free(ptr, n);
+ p.ordered_free(ptr, n);
}
static bool release_memory()
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.release_memory(); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- return p.p.release_memory();
+ return p.release_memory();
}
static bool purge_memory()
- {
- pool_type & p = singleton::instance();
+ { //! Equivalent to SingletonPool::p.purge_memory(); synchronized.
+ pool_type & p = get_pool();
details::pool::guard<Mutex> g(p);
- return p.p.purge_memory();
+ return p.purge_memory();
}
-};
+
+private:
+ typedef boost::aligned_storage<sizeof(pool_type), boost::alignment_of<pool_type>::value> storage_type;
+ static storage_type storage;
+
+ static pool_type& get_pool()
+ {
+ static bool f = false;
+ if(!f)
+ {
+ // This code *must* be called before main() starts,
+ // and when only one thread is executing.
+ f = true;
+ new (&storage) pool_type;
+ }
+
+ // The following line does nothing else than force the instantiation
+ // of singleton<T>::create_object, whose constructor is
+ // called before main() begins.
+ create_object.do_nothing();
+
+ return *static_cast<pool_type*>(static_cast<void*>(&storage));
+ }
+
+ struct object_creator
+ {
+ object_creator()
+ { // This constructor does nothing more than ensure that instance()
+ // is called before main() begins, thus creating the static
+ // T object before multithreading race issues can come up.
+ singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::get_pool();
+ }
+ inline void do_nothing() const
+ {
+ }
+ };
+ static object_creator create_object;
+}; // struct singleton_pool
+
+template <typename Tag,
+ unsigned RequestedSize,
+ typename UserAllocator,
+ typename Mutex,
+ unsigned NextSize,
+ unsigned MaxSize >
+typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage_type singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage;
+
+template <typename Tag,
+ unsigned RequestedSize,
+ typename UserAllocator,
+ typename Mutex,
+ unsigned NextSize,
+ unsigned MaxSize >
+typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::object_creator singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::create_object;
} // namespace boost
Deleted: branches/release/libs/pool/TODO.txt
==============================================================================
--- branches/release/libs/pool/TODO.txt 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,10 +0,0 @@
-Copyright (C) 2000 Stephen Cleary
-
-Distributed under the Boost Software License, Version 1.0. (See accompany-
-ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-Here's a list of things TODO on the Pool library; these things will be done on an "as-I-get-around-to-it" basis:
- . Evaluate changes necessary for MSVC 6sp4 (Could use some help from people who own MSVC...)
- . Create more exhaustive test/example files, possibly other timing tests; convert to the new Boost testing harness
- . Add overloaded new/delete (pool_base) as Yet Another Interface.
- . Add a "grow" function (similar to std::realloc) to pool for attempting reallocation of contiguous memory; if it fails to find contiguous chunks, it should return 0.
Deleted: branches/release/libs/pool/doc/concepts.html
==============================================================================
--- branches/release/libs/pool/doc/concepts.html 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,407 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-"http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-<head>
- <meta http-equiv="Content-Language" content="en-us">
- <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
- <link href="pool.css" rel="stylesheet" type="text/css">
-
- <title>Pool Concepts</title>
-</head>
-
-<body>
- <img src="../../../boost.png" width="276" height="86" alt="C++ Boost">
-
- <h1 align="center">Pool Concepts</h1>
-
- <blockquote>
- "Dynamic memory allocation has been a fundamental part of most computer
- systems since roughly 1960..."<sup>1</sup>
- </blockquote>
-
- <p>Everyone uses dynamic memory allocation. If you have ever called
- <span class="code">malloc</span> or <span class="code">new</span>, then you
- have used dynamic memory allocation. Most programmers have a tendency to
- treat the heap as a "magic bag": we ask it for memory, and it magically
- creates some for us. Sometimes we run into problems because the heap is
- <em>not</em> magic.</p>
-
- <p>The heap is limited. Even on large systems (i.e., not embedded) with
- huge amounts of virtual memory available, there is a limit. Everyone is
- aware of the physical limit, but there is a more subtle, "virtual" limit,
- that limit at which your program (or the entire system) slows down due to
- the use of virtual memory. This virtual limit is much closer to your
- program than the physical limit, especially if you are running on a
- multitasking system. Therefore, when running on a large system, it is
- considered "nice" to make your program use as few resources as necessary,
- and release them as soon as possible. When using an embedded system,
- programmers usually have no memory to waste.</p>
-
- <p>The heap is complicated. It has to satisfy any type of memory request,
- for any size, and do it <em>fast</em>. The common approaches to memory
- management have to do with splitting the memory up into portions, and
- keeping them ordered by size in some sort of a tree or list structure. Add
- in other factors, such as locality and estimating lifetime, and heaps
- quickly become very complicated. So complicated, in fact, that there is no
- known "perfect" answer to the problem of how to do dynamic memory
- allocation. The diagrams below illustrate how most common memory managers
- work: for each chunk of memory, it uses part of that memory to maintain its
- internal tree or list structure. Even when a chunk is <span class=
- "code">malloc</span>'ed out to a program, the memory manager must "save"
- some information in it — usually just its size. Then, when the block
- is <span class="code">free</span>'d, the memory manager can easily tell how
- large it is.</p>
-
- <table cellspacing="0" border="3" rules="none" style=
- "float: left; clear: both;" summary="">
- <caption>
- <em>Memory block, not allocated</em>
- </caption>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: silver; text-align: center;">
- Memory used internally by memory allocator algorithm (usually 8-12
- bytes)</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 2em 0em; background-color: gray; text-align: center">Unused
- memory</td>
- </tr>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
- </table>
-
- <table cellspacing="0" border="3" rules="none" style=
- "float: right; clear: both;" summary="">
- <caption>
- <em>Memory block, allocated (used by program)</em>
- </caption>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
-
- <tr>
- <td style="background-color: silver; text-align: center;">Memory used
- internally by memory allocator algorithm (usually 4 bytes)</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 3em 0em; background-color: yellow; text-align: center">Memory
- usable by program</td>
- </tr>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
- </table>
-
- <p>Because of the complication of dynamic memory allocation, it is often
- inefficient in terms of time and/or space. Most memory allocation
- algorithms store some form of information with each memory block, either
- the block size or some relational information, such as its position in the
- internal tree or list structure. It is common for such "header fields" to
- take up one machine word in a block that is being used by the program. The
- obvious problem, then, is when small objects are dynamically allocated. For
- example, if <span class="code">int</span>s were dynamically allocated, then
- automatically the algorithm will reserve space for the header fields as
- well, and we end up with a 50% waste of memory. Of course, this is a
- worst-case scenario. However, more modern programs are making use of small
- objects on the heap; and that is making this problem more and more
- apparent. Wilson <em>et. al.</em> state that an average-case memory
- overhead is about ten to twenty percent<sup>2</sup>.
- This memory overhead will grow higher as more programs use more smaller
- objects. It is this memory overhead that brings programs closer to the
- virtual limit.</p>
-
- <p>In larger systems, the memory overhead is not as big of a problem
- (compared to the amount of time it would take to work around it), and thus
- is often ignored. However, there are situations where many allocations
- and/or deallocations of smaller objects are taking place as part of a
- time-critical algorithm, and in these situations, the system-supplied
- memory allocator is often too slow.</p>
-
- <p>Simple segregated storage addresses both of these issues. Almost all
- memory overhead is done away with, and all allocations can take place in a
- small amount of (amortized) constant time. However, this is done at the
- loss of generality; simple segregated storage only can allocate memory
- chunks of a single size.</p>
- <hr>
-
- <h1 align="center">Simple Segregated Storage</h1>
-
- <p>Simple Segregated Storage is the basic idea behind the Boost Pool
- library. Simple Segregated Storage is the simplest, and probably the
- fastest, memory allocation/deallocation algorithm. It begins by
- <em>partitioning</em> a memory <em>block</em> into fixed-size
- <em>chunks</em>. Where the block comes from is not important until
- implementation time. A <em>Pool</em> is some object that uses Simple
- Segregated Storage in this fashion. To illustrate:</p>
-
- <table cellspacing="0" border="3" rules="none" align="center" style=
- "clear: both;" summary="">
- <caption>
- <em>Memory block, split into chunks</em>
- </caption>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 0</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 1</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 2</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 3</td>
- </tr>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
- </table>
-
- <p>Each of the chunks in any given block are <strong>always</strong> the
- same size. This is the fundamental restriction of Simple Segregated
- Storage: you cannot ask for chunks of different sizes. For example, you
- cannot ask a Pool of integers for a character, or a Pool of characters for
- an integer (assuming that characters and integers are different sizes).</p>
-
- <p>Simple Segregated Storage works by interleaving a <em>free list</em>
- within the unused chunks. For example:</p>
-
- <table cellspacing="0" border="3" rules="none" style=
- "float: left; clear: both;" summary="">
- <caption>
- <em>Memory block, with no chunks allocated</em>
- </caption>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 0; points to Chunk 1</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 1; points to Chunk 2</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 2; points to Chunk 3</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 3; end-of-list</td>
- </tr>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
- </table>
-
- <table cellspacing="0" border="3" rules="none" style=
- "float: right; clear: both;" summary="">
- <caption>
- <em>Memory block, with two chunks allocated</em>
- </caption>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 0; points to Chunk 2</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: silver; text-align: center;">Chunk
- 1 (in use by process)</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: gray; text-align: center;">Chunk
- 2; end-of-list</td>
- </tr>
-
- <tr>
- <td style=
- "padding: 1em 0em; background-color: silver; text-align: center;">Chunk
- 3 (in use by process)</td>
- </tr>
-
- <tr>
- <td style="background-color: red; text-align: center;">Memory not
- belonging to process</td>
- </tr>
- </table>
-
- <p>By interleaving the free list inside the chunks, each Simple Segregated
- Storage only has the overhead of a single pointer (the pointer to the first
- element in the list). It has <em>no</em> memory overhead for chunks that
- are in use by the process.</p>
-
- <p>Simple Segregated Storage is also extremely fast. In the simplest case,
- memory allocation is merely removing the first chunk from the free list, a
- O(1) operation. In the case where the free list is empty, another block may
- have to be acquired and partitioned, which would result in an amortized
- O(1) time. Memory deallocation may be as simple as adding that chunk to the
- front of the free list, a O(1) operation. However, more complicated uses of
- Simple Segregated Storage may require a sorted free list, which makes
- deallocation O(N).</p>
-
- <p>Simple Segregated Storage gives faster execution and less memory
- overhead than a system-supplied allocator, but at the loss of generality. A
- good place to use a Pool is in situations where many (noncontiguous) small
- objects may be allocated on the heap, or if allocation and deallocation of
- the same-sized objects happens repeatedly.<br clear="all"></p>
- <hr>
-
- <h2>References</h2>
-
- <ol>
- <li><a name="ref1" id="ref1">Doug Lea, <em>A Memory Allocator</em>.</a>
- Available on the web at <a href=
- "http://gee.cs.oswego.edu/dl/html/malloc.html">http://gee.cs.oswego.edu/dl/html/malloc.html></li>
-
- <li><a name="ref2" id="ref2">Paul R. Wilson, Mark S. Johnstone, Michael
- Neely, and David Boles, "Dynamic Storage Allocation: A Survey and
- Critical Review" in <em>International Workshop on Memory Management</em>,
- September 1995, pg. 28, 36.</a> Available on the web at <a href=
- "ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps">ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps></li>
- </ol>
-
- <h2>Other Implementations</h2>
-
- <p>Pool allocators are found in many programming languages, and in many
- variations. The beginnings of many implementations may be found in common
- programming literature; some of these are given below. Note that none of
- these are complete implementations of a Pool; most of these leave some
- aspects of a Pool as a user exercise. However, in each case, even though
- some aspects are missing, these examples use the same underlying concept of
- a Simple Segregated Storage described in this document.</p>
-
- <ul>
- <li>"The C++ Programming Language", 3rd ed., by Bjarne Stroustrup,
- Section 19.4.2. Missing aspects:
-
- <ol>
- <li>Not portable</li>
-
- <li>Cannot handle allocations of arbitrary numbers of objects (this
- was left as an exercise)</li>
-
- <li>Not thread-safe</li>
-
- <li>Suffers from the static initialization problem</li>
- </ol>
- </li>
-
- <li>"MicroC/OS-II: The Real-Time Kernel", by Jean J. Labrosse, Chapter 7
- and Appendix B.04. This is an example of the Simple Segregated Storage
- scheme at work in the internals of an actual OS. Missing aspects:
-
- <ol>
- <li>Not portable (though this is OK, since it's part of its own
- OS)</li>
-
- <li>Cannot handle allocations of arbitrary numbers of blocks (which
- is also OK, since this feature is not needed)</li>
-
- <li>Requires non-intuitive user code to create and destroy the
- Pool</li>
- </ol>
- </li>
-
- <li>"Efficient C++: Performance Programming Techniques", by Dov Bulka and
- David Mayhew, Chapters 6 and 7. This is a good example of iteratively
- developing a Pool solution; however, their premise (that the
- system-supplied allocation mechanism is hopelessly inefficient) is flawed
- on every system I've tested on. Run their timings on your system before
- you accept their conclusions. Missing aspects:
-
- <ol>
- <li>Requires non-intuitive user code to create and destroy the
- Pool</li>
- </ol>
- </li>
-
- <li>"Advanced C++: Programming Styles and Idioms", by James O. Coplien,
- Section 3.6. This has examples of both static and dynamic pooling.
- Missing aspects:
-
- <ol>
- <li>Not thread-safe</li>
-
- <li>The static pooling example is not portable</li>
- </ol>
- </li>
- </ul>
- <hr>
-
- <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
- "../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
- height="31" width="88"></a></p>
-
- <p>Revised
- <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
- December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
-
- <p><i>Copyright © 2000, 2001 Stephen Cleary (scleary AT jerviswebb DOT
- com)</i></p>
-
- <p><i>Distributed under the Boost Software License, Version 1.0. (See
- accompanying file LICENSE_1_0.txt or
- copy at <a href=
- "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
-</body>
-</html>
Deleted: branches/release/libs/pool/doc/index.html
==============================================================================
--- branches/release/libs/pool/doc/index.html 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,231 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-"http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-<head>
- <meta http-equiv="Content-Language" content="en-us">
- <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
- <link href="pool.css" rel="stylesheet" type="text/css">
-
- <title>Boost Pool Library</title>
-</head>
-
-<body>
- <img src="../../../boost.png" width="276" height="86" alt="C++ Boost">
-
- <h1 align="center">Boost Pool Library</h1>
-
- <h2>Introduction</h2>
-
- <h3>What is Pool?</h3>
-
- <p>Pool allocation is a memory allocation scheme that is very fast, but
- limited in its usage. For more information on pool allocation (also called
- "simple segregated storage"), see <a href="concepts.html">the concepts
- document</a>.</p>
-
- <h3>Why should I use Pool?</h3>
-
- <p>Using Pools gives you more control over how memory is used in your
- program. For example, you could have a situation where you want to allocate
- a bunch of small objects at one point, and then reach a point in your
- program where none of them are needed any more. Using pool interfaces, you
- can choose to run their destructors or just drop them off into oblivion; the
- pool interface will guarantee that there are no system memory leaks.</p>
-
- <h3>When should I use Pool?</h3>
-
- <p>Pools are generally used when there is a lot of allocation and
- deallocation of small objects. Another common usage is the situation above,
- where many objects may be dropped out of memory.</p>
-
- <p>In general, use Pools when you need a more efficient way to do unusual
- memory control.</p>
-
- <h3>How do I use Pool?</h3>
-
- <p>See the pool interfaces document, which
- covers the different Pool interfaces supplied by this library.</p>
-
- <h2>Library Structure and Dependencies</h2>
-
- <p>Forward declarations of all the exposed symbols for this library are in
- the header <span class="code"><boost/pool/poolfwd.hpp></span>.</p>
-
- <p>The library may use macros, which will be prefixed with <span class=
- "code">BOOST_POOL_</span>. The exception to this rule are the include file
- guards, which (for file <em>xxx</em>.hpp) is <span class=
- "code">BOOST_<em>xxx</em>_HPP</span>.</p>
-
- <p>All exposed symbols defined by the library will be in namespace
- <span class="code">boost</span>. All symbols used only by the implementation
- will be in namespace <span class=
- "code">boost::details::pool</span>.</p>
-
- <p>Every header used only by the implementation is in the subdirectory
- <span class="code">detail/</span>.</p>
-
- <p>Any header in the library may include any other header in the library or
- any system-supplied header at its discretion.</p>
-
- <h2>Installation</h2>
-
- <p>The Boost Pool library is a header file library. That means there is no
- .lib, .dll, or .so to build; just add the Boost directory to your compiler's
- include file path, and you should be good to go!</p>
-
- <h2>Building the Test Programs</h2>
-
- <p>The subdirectory "build" contains subdirectories for several different
- platforms. These subdirectories contain all necessary work-around code for
- that platform, as well as makefiles or IDE project files as appropriate.</p>
-
- <p>Read the "readme.txt" in the proper subdirectory, if it exists.</p>
-
- <p>The standard makefile targets are "all", "clean" (which deletes any
- intermediate files), and "veryclean" (which deletes any intermediate files
- and executables). All intermediate and executable files are built in the
- same directory as the makefile/project file. If there is a project file
- supplied instead of a makefile, "clean" and "veryclean" shell scripts/batch
- files will be provided.</p>
-
- <p>Project files and makefiles for additional platforms may be sent to
- Stephen Cleary at scleary AT jerviswebb DOT com.</p>
-
- <h2>Documentation Map</h2>
-
- <ul>
- <li>Overview of Pooling
-
- <ul>
- <li>concepts.html - The basic ideas behind
- pooling.</li>
-
- <li><a href=
- "implementation/alignment.html">implementation/alignment.html</a> -
- How we guarantee alignment portably.</li>
-
- <li>interfaces.html - What interfaces
- are provided and when to use each one.</li>
- </ul>
- </li>
-
- <li>Pool Exposed Interfaces
-
- <ul>
- <li><a href=
- "interfaces/simple_segregated_storage.html">
- interfaces/simple_segregated_storage.html</a>
- - Not for the faint of heart; embedded programmers only.</li>
-
- <li>interfaces/pool.html - The
- basic pool interface.</li>
-
- <li><a href=
- "interfaces/singleton_pool.html">interfaces/singleton_pool.html</a> -
- The basic pool interface as a thread-safe singleton.</li>
-
- <li><a href=
- "interfaces/object_pool.html">interfaces/object_pool.html</a> - A
- type-oriented (instead of size-oriented) pool interface.</li>
-
- <li><a href=
- "interfaces/pool_alloc.html">interfaces/pool_alloc.html</a> - A
- Standard Allocator pool interface based on singleton_pool.</li>
-
- <li><a href=
- "interfaces/user_allocator.html">interfaces/user_allocator.html</a> -
- OK, not a pool interface, but it describes how the user can control
- how Pools allocate system memory.</li>
- </ul>
- </li>
-
- <li>Pool Implementation Details and Extensions
-
- <ul>
- <li>Interface Implementations and Extensions
-
- <ul>
- <li><a href=
- "implementation/simple_segregated_storage.html">
- implementation/simple_segregated_storage.html</a></li>
-
- <li><a href=
- "implementation/pool.html">implementation/pool.html</a></li>
-
- <li><a href=
- "implementation/singleton_pool.html">
- implementation/singleton_pool.html</a></li>
-
- <li><a href=
- "implementation/object_pool.html">implementation/object_pool.html</a></li>
-
- <li><a href=
- "implementation/pool_alloc.html">implementation/pool_alloc.html</a></li>
- </ul>
- </li>
-
- <li>Components Used Only by the Implementation
-
- <ul>
- <li><a href=
- "implementation/ct_gcd_lcm.html">implementation/ct_gcd_lcm.html</a>
- - Compile-time GCD and LCM.</li>
-
- <li>implementation/for.html
- - Description of an m4 component.</li>
-
- <li><a href=
- "implementation/gcd_lcm.html">implementation/gcd_lcm.html</a> -
- Run-time GCD and LCM.</li>
-
- <li><a href=
- "implementation/guard.html">implementation/guard.html</a> - Auto
- lock/unlock for mutex.</li>
-
- <li><a href=
- "implementation/mutex.html">implementation/mutex.html</a> -
- Platform-dependent mutex type.</li>
-
- <li><a href=
- "implementation/pool_construct.html">
- implementation/pool_construct.html</a>
- - The system for supporting more constructor arguments in
- object_pool.</li>
-
- <li><a href=
- "implementation/singleton.html">implementation/singleton.html</a>
- - Singleton that avoids static initialization problem.</li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
-
- <h2>Future Directions</h2>
-
- <p>Another pool interface will be written: a base class for per-class pool
- allocation.</p>
-
- <h2>Acknowledgements</h2>
-
- <p>Many, many thanks to the Boost peers, notably Jeff Garland, Beman Dawes,
- Ed Brey, Gary Powell, Peter Dimov, and Jens Maurer for providing helpful
- suggestions!</p>
- <hr>
-
- <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
- "../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
- height="31" width="88"></a></p>
-
- <p>Revised
- <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
-
- <p><i>Copyright © 2000, 2001 Stephen Cleary (scleary AT jerviswebb DOT com)</i></p>
-
- <p><i>Distributed under the Boost Software License, Version 1.0. (See
- accompanying file LICENSE_1_0.txt or
- copy at <a href=
- "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
-</body>
-</html>
Deleted: branches/release/libs/pool/doc/interfaces.html
==============================================================================
--- branches/release/libs/pool/doc/interfaces.html 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,153 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-"http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-<head>
- <meta http-equiv="Content-Language" content="en-us">
- <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
- <link href="pool.css" rel="stylesheet" type="text/css">
-
- <title>Boost Pool Interfaces</title>
-</head>
-
-<body>
- <img src="../../../boost.png" width="276" height="86" alt="C++ Boost">
-
- <h1 align="center">Boost Pool Interfaces</h1>
-
- <h2>Introduction</h2>
-
- <p>There are several interfaces provided which allow users great flexibility
- in how they want to use Pools. Review the <a href=
- "concepts.html">concepts document</a> to get the basic understanding of how
- Pools work.</p>
-
- <h2>Terminology and Tradeoffs</h2>
-
- <h3>Object Usage vs. Singleton Usage</h3>
-
- <p><em>Object Usage</em> is the method where each Pool is an object that may
- be created and destroyed. Destroying a Pool implicitly frees all chunks that
- have been allocated from it.</p>
-
- <p><em>Singleton Usage</em> is the method where each Pool is an object with
- static duration; that is, it will not be destroyed until program exit. Pool
- objects with Singleton Usage may be shared; thus, Singleton Usage implies
- thread-safety as well. System memory allocated by Pool objects with
- Singleton Usage may be freed through <span class=
- "code">release_memory</span> or <span class="code">purge_memory</span>.</p>
-
- <h3>Out-of-Memory Conditions: Exceptions vs. Null Return</h3>
-
- <p>Some Pool interfaces throw exceptions when out-of-memory; others will
- return 0. In general, unless mandated by the Standard, Pool interfaces will
- always prefer to return 0 instead of throw an exception.</p>
-
- <h2>The Interfaces</h2>
-
- <h3>pool</h3>
-
- <p>The pool interface is a simple Object
- Usage interface with Null Return.</p>
-
- <p>Example:</p>
- <pre class="code">
-void func()
-{
- boost::pool<> p(sizeof(int));
- for (int i = 0; i < 10000; ++i)
- {
- int * const t = p.malloc();
- ... // Do something with t; don't take the time to free() it
- }
-} // on function exit, p is destroyed, and all malloc()'ed ints are implicitly freed
-</pre>
-
- <h3>object_pool</h3>
-
- <p>The object_pool interface is an
- Object Usage interface with Null Return, but is aware of the type of the
- object for which it is allocating chunks. On destruction, any chunks that
- have been allocated from that object_pool will have their destructors
- called.</p>
-
- <p>Example:</p>
- <pre class="code">
-struct X { ... }; // has destructor with side-effects
-
-void func()
-{
- boost::object_pool<X> p;
- for (int i = 0; i < 10000; ++i)
- {
- X * const t = p.malloc();
- ... // Do something with t; don't take the time to free() it
- }
-} // on function exit, p is destroyed, and all destructors for the X objects are called
-</pre>
-
- <h3>singleton_pool</h3>
-
- <p>The singleton_pool interface
- is a Singleton Usage interface with Null Return. It's just the same as the
- pool interface but with Singleton Usage instead.</p>
-
- <p>Example:</p>
- <pre class="code">
-struct MyPoolTag { };
-
-typedef boost::singleton_pool<MyPoolTag, sizeof(int)> my_pool;
-void func()
-{
- for (int i = 0; i < 10000; ++i)
- {
- int * const t = my_pool::malloc();
- ... // Do something with t; don't take the time to free() it
- }
- // Explicitly free all malloc()'ed int's
- my_pool::purge_memory();
-}
-</pre>
-
- <h3>pool_alloc</h3>
-
- <p>The pool_alloc interface is a
- Singleton Usage interface with Exceptions. It is built on the singleton_pool
- interface, and provides a Standard Allocator-compliant class (for use in
- containers, etc.).</p>
-
- <p>Example:</p>
- <pre class="code">
-void func()
-{
- std::vector<int, boost::pool_allocator<int> > v;
- for (int i = 0; i < 10000; ++i)
- v.push_back(13);
-} // Exiting the function does NOT free the system memory allocated by the pool allocator
- // You must call
- // boost::singleton_pool<boost::pool_allocator_tag, sizeof(int)>::release_memory()
- // in order to force that
-</pre>
-
- <h2>Future Directions</h2>
-
- <p>Another pool interface will be written: a base class for per-class pool
- allocation. This "pool_base" interface will be Singleton Usage with
- Exceptions, and built on the singleton_pool interface.</p>
- <hr>
-
- <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
- "../../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
- height="31" width="88"></a></p>
-
- <p>Revised
- <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
-
- <p><i>Copyright © 2000, 2001 Stephen Cleary (scleary AT jerviswebb DOT com)</i></p>
-
- <p><i>Distributed under the Boost Software License, Version 1.0. (See
- accompanying file LICENSE_1_0.txt or
- copy at <a href=
- "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
-</body>
-</html>
Deleted: branches/release/libs/pool/doc/pool.css
==============================================================================
--- branches/release/libs/pool/doc/pool.css 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,9 +0,0 @@
-/*
- Copyright (C) 2000 Stephen Cleary
-
- Distributed under the Boost Software License, Version 1.0. (See accompany-
- ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-*/
-
-*.code { font-family: monospace; }
-*.m4 { white-space: pre; font-family: monospace; font-size: 75% }
\ No newline at end of file
Modified: branches/release/libs/pool/index.html
==============================================================================
--- branches/release/libs/pool/index.html (original)
+++ branches/release/libs/pool/index.html 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -1,13 +1,13 @@
<html>
<head>
-<meta http-equiv="refresh" content="0; URL=doc/index.html">
+<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
</head>
<body>
Automatic redirection failed, please go to
-doc/index.html. <hr>
+doc/html/index.html. <hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy
at www.boost.org/LICENSE_1_0.txt)</p>
</body>
-</html>
\ No newline at end of file
+</html>
Modified: branches/release/libs/pool/test/Jamfile.v2
==============================================================================
--- branches/release/libs/pool/test/Jamfile.v2 (original)
+++ branches/release/libs/pool/test/Jamfile.v2 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -2,14 +2,71 @@
#~ 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)
+
project
: requirements
<library>/boost/test//boost_test_exec_monitor/<link>static
+ <include>../../..
+ <define>BOOST_ALL_NO_LIB=1
+ <warnings>all
+ <toolset>gcc:<cxxflags>-Wextra
+ <toolset>gcc:<cxxflags>-Wshadow
+ <toolset>gcc:<warnings-as-errors>on
+ <toolset>gcc:<cxxflags>-Wno-long-long
+ <toolset>pathscale:<cxxflags>-Wno-long-long
+ <toolset>gcc:<cxxflags>-Wcast-align
+ <toolset>msvc:<warnings-as-errors>on
;
import testing ;
+run valgrind_config_check.cpp : : : <testing.launcher>"valgrind --error-exitcode=1" ;
+explicit valgrind_config_check ;
+
test-suite pool :
+ [ run test_simple_seg_storage.cpp ]
[ run test_pool_alloc.cpp ]
[ run pool_msvc_compiler_bug_test.cpp ]
+ [ run test_msvc_mem_leak_detect.cpp ]
+ [ run test_bug_3349.cpp ]
+ [ run test_bug_4960.cpp ]
+ [ run test_bug_1252.cpp ]
+ [ run test_bug_2696.cpp ]
+ [ run test_bug_5526.cpp ]
+ [ run test_threading.cpp : : : <threading>multi <library>/boost/thread//boost_thread <toolset>gcc:<cxxflags>-Wno-attributes <toolset>gcc:<cxxflags>-Wno-missing-field-initializers ]
+ [ run ../example/time_pool_alloc.cpp ]
+ [ compile test_poisoned_macros.cpp ]
+
+#
+# The following tests test Boost.Pool's code with valgrind only if it's available:
+#
+ [ run test_simple_seg_storage.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_simple_seg_storage_valgrind ]
+ [ run test_pool_alloc.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_pool_alloc_valgrind ]
+ [ run pool_msvc_compiler_bug_test.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : pool_msvc_compiler_bug_test_valgrind ]
+ [ run test_msvc_mem_leak_detect.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_msvc_mem_leak_detect_valgrind ]
+ [ run test_bug_3349.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_3349_valgrind ]
+ [ run test_bug_4960.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_4960_valgrind ]
+ [ run test_bug_1252.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_1252_valgrind ]
+ [ run test_bug_2696.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_2696_valgrind ]
+ [ run test_bug_5526.cpp : : : [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_5526_valgrind ]
+ [ run test_threading.cpp : : : <threading>multi <library>/boost/thread//boost_thread <toolset>gcc:<cxxflags>-Wno-attributes <toolset>gcc:<cxxflags>-Wno-missing-field-initializers [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_threading_valgrind ]
+
+#
+# The following tests test Boost.Pool's code with valgrind if it's available, and in any case with BOOST_POOL_VALGRIND defined
+# which has the effect of disabling any actual memory pooling:
+#
+ [ run test_simple_seg_storage.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_simple_seg_storage_valgrind_2 ]
+ [ run test_pool_alloc.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_pool_alloc_valgrind_2 ]
+ [ run pool_msvc_compiler_bug_test.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : pool_msvc_compiler_bug_test_valgrind_2 ]
+ [ run test_msvc_mem_leak_detect.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_msvc_mem_leak_detect_valgrind_2 ]
+ [ run test_bug_3349.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_3349_valgrind_2 ]
+ [ run test_bug_4960.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_4960_valgrind_2 ]
+ [ run test_bug_1252.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_1252_valgrind_2 ]
+ [ run test_bug_2696.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_2696_valgrind_2 ]
+ [ run test_bug_5526.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_bug_5526_valgrind_2 ]
+ [ run test_threading.cpp : : : <threading>multi <library>/boost/thread//boost_thread <define>BOOST_POOL_VALGRIND=1 <toolset>gcc:<cxxflags>-Wno-attributes <toolset>gcc:<cxxflags>-Wno-missing-field-initializers [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_threading_valgrind_2 ]
+ [ run-fail test_valgrind_fail_1.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] ]
+ [ run-fail test_valgrind_fail_2.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] ]
;
+
+
Deleted: branches/release/libs/pool/test/sys_allocator.hpp
==============================================================================
--- branches/release/libs/pool/test/sys_allocator.hpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,100 +0,0 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// 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)
-
-#ifndef BOOST_SYS_ALLOCATOR_H
-#define BOOST_SYS_ALLOCATOR_H
-
-// Symbols: malloc_allocator, new_delete_allocator
-
-#include <cstddef>
-#include <cstdlib>
-#include <boost/limits.hpp>
-#include <new>
-
-template <typename T>
-struct malloc_allocator
-{
- typedef T * pointer;
- typedef const T * const_pointer;
- typedef T & reference;
- typedef const T & const_reference;
- typedef T value_type;
-
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- template <typename U>
- struct rebind
- {
- typedef malloc_allocator<U> other;
- };
-
- static pointer address(reference r) { return &r; }
- static const_pointer address(const_reference r) { return &r; }
- static pointer allocate(const size_type n, const pointer = 0)
- {
- const pointer ret = (pointer) std::malloc(n * sizeof(T));
- if (ret == 0)
- throw std::bad_alloc();
- return ret;
- }
- static void deallocate(const pointer p, const size_type)
- { std::free(p); }
- static size_type max_size() { return (std::numeric_limits<size_type>::max)(); }
-
- bool operator==(const malloc_allocator &) const { return true; }
- bool operator!=(const malloc_allocator &) const { return false; }
-
- malloc_allocator() { }
- template <typename U>
- malloc_allocator(const malloc_allocator<U> &) { }
-
- static void construct(const pointer p, const_reference t)
- { new ((void *) p) T(t); }
- static void destroy(const pointer p)
- { p->~T(); }
-};
-
-template <typename T>
-struct new_delete_allocator
-{
- typedef T * pointer;
- typedef const T * const_pointer;
- typedef T & reference;
- typedef const T & const_reference;
- typedef T value_type;
-
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- template <typename U>
- struct rebind
- {
- typedef new_delete_allocator<U> other;
- };
-
- static pointer address(reference r) { return &r; }
- static const_pointer address(const_reference r) { return &r; }
- static pointer allocate(const size_type n, const pointer = 0)
- { return (pointer) new char[n * sizeof(T)]; }
- static void deallocate(const pointer p, const size_type)
- { delete [] p; }
- static size_type max_size() { return (std::numeric_limits<size_type>::max)(); }
-
- bool operator==(const new_delete_allocator &) const { return true; }
- bool operator!=(const new_delete_allocator &) const { return false; }
-
- new_delete_allocator() { }
- template <typename U>
- new_delete_allocator(const new_delete_allocator<U> &) { }
-
- static void construct(const pointer p, const_reference t)
- { new ((void *) p) T(t); }
- static void destroy(const pointer p)
- { p->~T(); }
-};
-
-#endif
Modified: branches/release/libs/pool/test/test_pool_alloc.cpp
==============================================================================
--- branches/release/libs/pool/test/test_pool_alloc.cpp (original)
+++ branches/release/libs/pool/test/test_pool_alloc.cpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
@@ -1,322 +1,272 @@
-// Copyright (C) 2000, 2001 Stephen Cleary
-//
-// 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)
-
-// Uncomment this to stub out all MT locking
-#define BOOST_NO_MT
+/* Copyright (C) 2000, 2001 Stephen Cleary
+ * Copyright (C) 2011 Kwan Ting Chan
+ *
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
#include <boost/pool/pool_alloc.hpp>
#include <boost/pool/object_pool.hpp>
-#include <stdlib.h>
-#include <stdexcept>
-#include <iostream>
-#include <vector>
+#include <boost/detail/lightweight_test.hpp>
+
#include <algorithm>
-#include <list>
#include <deque>
+#include <list>
#include <set>
+#include <stdexcept>
+#include <vector>
-// use of test_main() eases automatic regression testing by eliminating
-// the need for manual intervention on test failures (Beman Dawes)
-#include <boost/test/test_tools.hpp>
-
-// VERBOSE will print out trace-like statements to show exactly what this
-// test file is doing.
-//#define VERBOSE
+#include <cstdlib>
+#include <ctime>
// Each "tester" object below checks into and out of the "cdtor_checker",
-// which will report any problems related to the construction/destruction of
+// which will check for any problems related to the construction/destruction of
// "tester" objects.
class cdtor_checker
{
- private:
+private:
// Each constructed object registers its "this" pointer into "objs"
- std::set<void *> objs;
+ std::set<void*> objs;
+
+public:
+ // True iff all objects that have checked in have checked out
+ bool ok() const { return objs.empty(); }
- public:
~cdtor_checker()
{
- // At end of program, print out memory leaks
- // (assuming no static "tester"s)
- for (std::set<void *>::const_iterator i = objs.begin();
- i != objs.end(); ++i)
- std::cout << "Memory leak: " << *i << std::endl;
+ BOOST_TEST(ok());
}
void check_in(void * const This)
{
- if (objs.find(This) != objs.end())
- std::cout << "Double-constructed memory: " << This << std::endl;
- objs.insert(This);
+ BOOST_TEST(objs.find(This) == objs.end());
+ objs.insert(This);
}
+
void check_out(void * const This)
{
- std::set<void *>::iterator i = objs.find(This);
- if (i == objs.end())
- std::cout << "Destroyed non-constructed memory: " << This << std::endl;
- objs.erase(This);
+ BOOST_TEST(objs.find(This) != objs.end());
+ objs.erase(This);
}
-
- // true iff all objects that have checked in have checked out
- bool ok() const { return objs.empty(); }
};
static cdtor_checker mem;
struct tester
{
- tester(int arg1, int arg2)
- {
- if (arg1 == 17 && arg2 == 17)
- {
-#ifdef VERBOSE
- std::cout << this << ": tester not constructed" << std::endl;
-#endif
- throw std::logic_error("No construction allowed!");
- }
-#ifdef VERBOSE
- std::cout << this << ": tester::tester()" << std::endl;
-#endif
- mem.check_in(this);
- }
-#ifdef VERBOSE
- tester(const tester & other)
- {
- std::cout << this << ": tester::tester(" << &other << ')' << std::endl;
-#else
- tester(const tester &)
- {
-#endif
- mem.check_in(this);
- }
- ~tester()
- {
-#ifdef VERBOSE
- std::cout << this << ": tester::~tester()" << std::endl;
-#endif
- mem.check_out(this);
- }
-};
+ tester(bool throw_except = false)
+ {
+ if(throw_except)
+ {
+ throw std::logic_error("Deliberate constructor exception");
+ }
-void test()
-{
- {
- // should do nothing
- boost::object_pool<tester> pool;
- }
-
- {
- // Construct several tester objects. Don't delete them (i.e.,
- // test pool's garbage collection).
-#ifdef VERBOSE
- std::cout << "Testing pool. . ." << std::endl;
-#endif
- boost::object_pool<tester> pool;
- for (int i = 0; i < 10; ++i)
- pool.construct(13, 13);
- }
-
- {
- // Construct several tester objects. Delete some of them.
-#ifdef VERBOSE
- std::cout << "Testing pool with some removed. . ." << std::endl;
-#endif
- boost::object_pool<tester> pool;
- std::vector<tester *> v;
- for (int i = 0; i < 10; ++i)
- v.push_back(pool.construct(13, 13));
- std::random_shuffle(v.begin(), v.end());
- for (int j = 0; j < 5; ++j)
- pool.destroy(v[j]);
- }
-
- {
- // Test how pool reacts with constructors that throw exceptions.
- // Shouldn't have any memory leaks.
-#ifdef VERBOSE
- std::cout << "Testing with exceptional constructors :). . ." << std::endl;
-#endif
- boost::object_pool<tester> pool;
- for (int i = 0; i < 5; ++i)
- {
- pool.construct(13, 13);
- }
- for (int j = 0; j < 5; ++j)
- {
- try
- {
- // The following constructor will raise an exception.
- pool.construct(17, 17);
- }
- catch (const std::logic_error &) { }
+ mem.check_in(this);
}
- }
-}
-void test_alloc()
-{
-#ifdef VERBOSE
- std::cout << "Testing allocator. . ." << std::endl;
-#endif
-
- {
- // Allocate several tester objects. Delete one.
-#ifdef VERBOSE
- std::cout << "with vector. . ." << std::endl;
-#endif
- std::vector<tester, boost::pool_allocator<tester> > l;
- for (int i = 0; i < 10; ++i)
- l.push_back(tester(13, 13));
- l.pop_back();
- }
-
- {
- // Allocate several tester objects. Delete two.
-#ifdef VERBOSE
- std::cout << "with deque. . ." << std::endl;
-#endif
- std::deque<tester, boost::pool_allocator<tester> > l;
- for (int i = 0; i < 10; ++i)
- l.push_back(tester(13, 13));
- l.pop_back();
- l.pop_front();
- }
-
- {
- // Allocate several tester objects. Delete two.
-#ifdef VERBOSE
- std::cout << "with list. . ." << std::endl;
-#endif
- std::list<tester, boost::fast_pool_allocator<tester> > l;
- // lists rebind their allocators, so dumping is useless
- for (int i = 0; i < 10; ++i)
- l.push_back(tester(13, 13));
- l.pop_back();
- l.pop_front();
- }
-
- tester * tmp;
- {
- // Create a memory leak on purpose. (Allocator doesn't have
- // garbage collection)
-#ifdef VERBOSE
- std::cout << "Testing allocator cleanup. . ." << std::endl;
-#endif
- // (Note: memory leak)
- boost::pool_allocator<tester> a;
- tmp = a.allocate(1, 0);
- new (tmp) tester(13, 13);
- }
- if (mem.ok())
- std::cout << "Error: Pool allocator cleaned up!" << std::endl;
- // Remove memory checker entry (to avoid error later) and
- // clean up memory leak
- tmp->~tester();
- boost::pool_allocator<tester>::deallocate(tmp, 1);
-
- // test allocating zero elements
- {
- boost::pool_allocator<tester> alloc;
- tester* ip = alloc.allocate(0);
- alloc.deallocate(ip, 0);
- }
-}
+ tester(const tester &)
+ {
+ mem.check_in(this);
+ }
+
+ ~tester()
+ {
+ mem.check_out(this);
+ }
+};
-// This is a wrapper around a UserAllocator. It just registers alloc/dealloc
-// to/from the system memory. It's used to make sure pool's are allocating
+// This is a wrapper around a UserAllocator. It just registers alloc/dealloc
+// to/from the system memory. It's used to make sure pool's are allocating
// and deallocating system memory properly.
// Do NOT use this class with static or singleton pools.
template <typename UserAllocator>
struct TrackAlloc
{
- typedef typename UserAllocator::size_type size_type;
- typedef typename UserAllocator::difference_type difference_type;
+ typedef typename UserAllocator::size_type size_type;
+ typedef typename UserAllocator::difference_type difference_type;
- static std::set<char *> allocated_blocks;
+ static std::set<char *> allocated_blocks;
- static char * malloc BOOST_PREVENT_MACRO_SUBSTITUTION(const size_type bytes)
- {
- char * const ret = (UserAllocator::malloc)(bytes);
- allocated_blocks.insert(ret);
- return ret;
- }
- static void free BOOST_PREVENT_MACRO_SUBSTITUTION(char * const block)
- {
- if (allocated_blocks.find(block) == allocated_blocks.end())
- std::cout << "Free'd non-malloc'ed block: " << (void *) block << std::endl;
- allocated_blocks.erase(block);
- (UserAllocator::free)(block);
- }
+ static char * malloc(const size_type bytes)
+ {
+ char * const ret = UserAllocator::malloc(bytes);
+ allocated_blocks.insert(ret);
+ return ret;
+ }
- static bool ok() { return allocated_blocks.empty(); }
+ static void free(char * const block)
+ {
+ BOOST_TEST(allocated_blocks.find(block) != allocated_blocks.end());
+ allocated_blocks.erase(block);
+ UserAllocator::free(block);
+ }
+
+ static bool ok()
+ {
+ return allocated_blocks.empty();
+ }
};
template <typename UserAllocator>
std::set<char *> TrackAlloc<UserAllocator>::allocated_blocks;
typedef TrackAlloc<boost::default_user_allocator_new_delete> track_alloc;
+void test()
+{
+ {
+ // Do nothing pool
+ boost::object_pool<tester> pool;
+ }
+
+ {
+ // Construct several tester objects. Don't delete them (i.e.,
+ // test pool's garbage collection).
+ boost::object_pool<tester> pool;
+ for(int i=0; i < 10; ++i)
+ {
+ pool.construct();
+ }
+ }
+
+ {
+ // Construct several tester objects. Delete some of them.
+ boost::object_pool<tester> pool;
+ std::vector<tester *> v;
+ for(int i=0; i < 10; ++i)
+ {
+ v.push_back(pool.construct());
+ }
+ std::random_shuffle(v.begin(), v.end());
+ for(int j=0; j < 5; ++j)
+ {
+ pool.destroy(v[j]);
+ }
+ }
+
+ {
+ // Test how pool reacts with constructors that throw exceptions.
+ // Shouldn't have any memory leaks.
+ boost::object_pool<tester> pool;
+ for(int i=0; i < 5; ++i)
+ {
+ pool.construct();
+ }
+ for(int j=0; j < 5; ++j)
+ {
+ try
+ {
+ // The following constructions will raise an exception.
+ pool.construct(true);
+ }
+ catch(const std::logic_error &) {}
+ }
+ }
+}
+
+void test_alloc()
+{
+ {
+ // Allocate several tester objects. Delete one.
+ std::vector<tester, boost::pool_allocator<tester> > l;
+ for(int i=0; i < 10; ++i)
+ {
+ l.push_back(tester());
+ }
+ l.pop_back();
+ }
+
+ {
+ // Allocate several tester objects. Delete two.
+ std::deque<tester, boost::pool_allocator<tester> > l;
+ for(int i=0; i < 10; ++i)
+ {
+ l.push_back(tester());
+ }
+ l.pop_back();
+ l.pop_front();
+ }
+
+ {
+ // Allocate several tester objects. Delete two.
+ std::list<tester, boost::fast_pool_allocator<tester> > l;
+ // lists rebind their allocators, so dumping is useless
+ for(int i=0; i < 10; ++i)
+ {
+ l.push_back(tester());
+ }
+ l.pop_back();
+ l.pop_front();
+ }
+
+ tester * tmp;
+ {
+ // Create a memory leak on purpose. (Allocator doesn't have
+ // garbage collection)
+ // (Note: memory leak)
+ boost::pool_allocator<tester> a;
+ tmp = a.allocate(1, 0);
+ new (tmp) tester();
+ }
+ if(mem.ok())
+ {
+ BOOST_ERROR("Pool allocator cleaned up itself");
+ }
+ // Remove memory checker entry (to avoid error later) and
+ // clean up memory leak
+ tmp->~tester();
+ boost::pool_allocator<tester>::deallocate(tmp, 1);
+
+ // test allocating zero elements
+ {
+ boost::pool_allocator<tester> alloc;
+ tester* ip = alloc.allocate(0);
+ alloc.deallocate(ip, 0);
+ }
+}
+
void test_mem_usage()
{
-#ifdef VERBOSE
- std::cout << "Testing memory usage. . ." << std::endl;
-#endif
-
- typedef boost::pool<track_alloc> pool_type;
-
- {
- // Constructor should do nothing; no memory allocation
- pool_type pool(sizeof(int));
- if (!track_alloc::ok())
- std::cout << "Memory error" << std::endl;
- if (pool.release_memory())
- std::cout << "Pool released memory" << std::endl;
- if (pool.purge_memory())
- std::cout << "Pool purged memory" << std::endl;
-
- // Should allocate from system
- (pool.free)((pool.malloc)());
- if (track_alloc::ok())
- std::cout << "Memory error" << std::endl;
-
- // Ask pool to give up memory it's not using; this should succeed
- if (!pool.release_memory())
- std::cout << "Pool didn't release memory" << std::endl;
- if (!track_alloc::ok())
- std::cout << "Memory error" << std::endl;
-
- // Should allocate from system again
- (pool.malloc)(); // loses the pointer to the returned chunk (*A*)
-
- // Ask pool to give up memory it's not using; this should fail
- if (pool.release_memory())
- std::cout << "Pool released memory" << std::endl;
-
- // Force pool to give up memory it's not using; this should succeed
- // This will clean up the memory leak from (*A*)
- if (!pool.purge_memory())
- std::cout << "Pool didn't purge memory" << std::endl;
- if (!track_alloc::ok())
- std::cout << "Memory error" << std::endl;
-
- // Should allocate from system again
- (pool.malloc)(); // loses the pointer to the returned chunk (*B*)
-
- // pool's destructor should purge the memory
- // This will clean up the memory leak from (*B*)
- }
+ typedef boost::pool<track_alloc> pool_type;
+
+ {
+ // Constructor should do nothing; no memory allocation
+ pool_type pool(sizeof(int));
+ BOOST_TEST(track_alloc::ok());
+ BOOST_TEST(!pool.release_memory());
+ BOOST_TEST(!pool.purge_memory());
+
+ // Should allocate from system
+ pool.free(pool.malloc());
+ BOOST_TEST(!track_alloc::ok());
+
+ // Ask pool to give up memory it's not using; this should succeed
+ BOOST_TEST(pool.release_memory());
+ BOOST_TEST(track_alloc::ok());
+
+ // Should allocate from system again
+ pool.malloc(); // loses the pointer to the returned chunk (*A*)
+
+ // Ask pool to give up memory it's not using; this should fail
+ BOOST_TEST(!pool.release_memory());
+
+ // Force pool to give up memory it's not using; this should succeed
+ // This will clean up the memory leak from (*A*)
+ BOOST_TEST(pool.purge_memory());
+ BOOST_TEST(track_alloc::ok());
- if (!track_alloc::ok())
- std::cout << "Memory error" << std::endl;
+ // Should allocate from system again
+ pool.malloc(); // loses the pointer to the returned chunk (*B*)
+
+ // pool's destructor should purge the memory
+ // This will clean up the memory leak from (*B*)
+ }
+
+ BOOST_TEST(track_alloc::ok());
}
void test_void()
{
-#ifdef VERBOSE
- std::cout << "Testing void specialization. . ." << std::endl;
-#endif
-
typedef boost::pool_allocator<void> void_allocator;
typedef boost::fast_pool_allocator<void> fast_void_allocator;
@@ -327,21 +277,14 @@
std::vector<int, fast_int_allocator> v2;
}
-int test_main(int, char * [])
+int main()
{
- test();
- test_alloc();
- test_mem_usage();
- test_void();
-
-#ifdef VERBOSE
- std::cout << "main() exiting. . ." << std::endl;
-#endif
- if (mem.ok() && track_alloc::ok())
- std::cout << "All tests passed!" << std::endl;
- else
- std::cout << "Memory inconsistent!" << std::endl;
- return 0;
-}
+ std::srand(static_cast<unsigned>(std::time(0)));
+ test();
+ test_alloc();
+ test_mem_usage();
+ test_void();
+ return boost::report_errors();
+}
Deleted: branches/release/libs/pool/test/time_pool_alloc.cpp
==============================================================================
--- branches/release/libs/pool/test/time_pool_alloc.cpp 2011-08-02 13:04:07 EDT (Tue, 02 Aug 2011)
+++ (empty file)
@@ -1,448 +0,0 @@
-// Copyright (C) 2000, 2001 Stephen Cleary
-//
-// 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)
-
-#include <boost/pool/pool_alloc.hpp>
-#include <boost/pool/object_pool.hpp>
-
-#include <iostream>
-#include <vector>
-#include <list>
-#include <set>
-
-#include <ctime>
-#include <cerrno>
-
-#include "sys_allocator.hpp"
-
-unsigned long num_ints;
-
-template <unsigned N>
-struct larger_structure
-{
- char data[N];
-};
-
-unsigned test_number;
-
-template <unsigned N>
-static void timing_test_alloc_larger()
-{
- typedef boost::fast_pool_allocator<larger_structure<N>,
- boost::default_user_allocator_new_delete,
- boost::details::pool::null_mutex> alloc;
- typedef boost::fast_pool_allocator<larger_structure<N> > alloc_sync;
-
- double end[1][6];
- std::clock_t start;
-
- start = std::clock();
- {
- std::allocator<larger_structure<N> > a;
- for (unsigned long i = 0; i < num_ints; ++i)
- a.deallocate(a.allocate(1), 1);
- }
- end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- std::free(std::malloc(sizeof(larger_structure<N>)));
- }
- end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- delete new (std::nothrow) larger_structure<N>;
- }
- end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- alloc::deallocate(alloc::allocate());
- }
- end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- alloc_sync::deallocate(alloc_sync::allocate());
- }
- end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- boost::pool<> p(sizeof(larger_structure<N>));
- for (unsigned long i = 0; i < num_ints; ++i)
- {
- void * const t = p.malloc();
- if (t != 0)
- p.free(t);
- }
- }
- end[0][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- std::cout << "Test " << test_number++ << ": Alloc & Dealloc " << num_ints << " structures of size " << sizeof(larger_structure<N>) << ":" << std::endl;
- std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
- std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
- std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
- std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
- std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
- std::cout << " Pool: " << end[0][5] << " seconds" << std::endl;
-}
-
-static void timing_test_alloc()
-{
- typedef boost::fast_pool_allocator<int,
- boost::default_user_allocator_new_delete,
- boost::details::pool::null_mutex> alloc;
- typedef boost::fast_pool_allocator<int> alloc_sync;
-
- double end[2][6];
- std::clock_t start;
-
- int ** p = new int*[num_ints];
-
- start = std::clock();
- {
- std::allocator<int> a;
- for (unsigned long i = 0; i < num_ints; ++i)
- a.deallocate(a.allocate(1), 1);
- }
- end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- std::free(std::malloc(sizeof(int)));
- }
- end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- delete new (std::nothrow) int;
- }
- end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- alloc::deallocate(alloc::allocate());
- }
- end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- alloc_sync::deallocate(alloc_sync::allocate());
- }
- end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- boost::pool<> p(sizeof(int));
- for (unsigned long i = 0; i < num_ints; ++i)
- {
- void * const t = p.malloc();
- if (t != 0)
- p.free(t);
- }
- }
- end[0][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
-
- start = std::clock();
- {
- std::allocator<int> a;
- for (unsigned long i = 0; i < num_ints; ++i)
- p[i] = a.allocate(1);
- for (unsigned long i = 0; i < num_ints; ++i)
- a.deallocate(p[i], 1);
- }
- end[1][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- p[i] = (int *) std::malloc(sizeof(int));
- for (unsigned long i = 0; i < num_ints; ++i)
- std::free(p[i]);
- }
- end[1][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- p[i] = new (std::nothrow) int;
- for (unsigned long i = 0; i < num_ints; ++i)
- delete p[i];
- }
- end[1][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- p[i] = alloc::allocate();
- for (unsigned long i = 0; i < num_ints; ++i)
- alloc::deallocate(p[i]);
- }
- end[1][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- for (unsigned long i = 0; i < num_ints; ++i)
- p[i] = alloc_sync::allocate();
- for (unsigned long i = 0; i < num_ints; ++i)
- alloc_sync::deallocate(p[i]);
- }
- end[1][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- boost::pool<> pl(sizeof(int));
- for (unsigned long i = 0; i < num_ints; ++i)
- p[i] = reinterpret_cast<int *>(pl.malloc());
- for (unsigned long i = 0; i < num_ints; ++i)
- if (p[i] != 0)
- pl.free(p[i]);
- }
- end[1][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- delete [] p;
-
- std::cout << "Test 3: Alloc & Dealloc " << num_ints << " ints:" << std::endl;
- std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
- std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
- std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
- std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
- std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
- std::cout << " Pool: " << end[0][5] << " seconds" << std::endl;
-
- std::cout << "Test 4: Alloc " << num_ints << " ints & Dealloc " << num_ints << " ints:" << std::endl;
- std::cout << " std::allocator: " << end[1][0] << " seconds" << std::endl;
- std::cout << " malloc/free: " << end[1][1] << " seconds" << std::endl;
- std::cout << " new/delete: " << end[1][2] << " seconds" << std::endl;
- std::cout << " Pool Alloc: " << end[1][3] << " seconds" << std::endl;
- std::cout << " Pool /w Sync: " << end[1][4] << " seconds" << std::endl;
- std::cout << " Pool: " << end[1][5] << " seconds" << std::endl;
-}
-
-static void timing_test_containers()
-{
- typedef boost::pool_allocator<int,
- boost::default_user_allocator_new_delete,
- boost::details::pool::null_mutex> alloc;
- typedef boost::pool_allocator<int> alloc_sync;
- typedef boost::fast_pool_allocator<int,
- boost::default_user_allocator_new_delete,
- boost::details::pool::null_mutex> fast_alloc;
- typedef boost::fast_pool_allocator<int> fast_alloc_sync;
-
- double end[3][5];
- std::clock_t start;
-
- start = std::clock();
- {
- std::vector<int, std::allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::vector<int, malloc_allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::vector<int, new_delete_allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::vector<int, alloc> x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::vector<int, alloc_sync> x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
-
- start = std::clock();
- {
- std::set<int, std::less<int>, std::allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.insert(0);
- }
- end[1][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::set<int, std::less<int>, malloc_allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.insert(0);
- }
- end[1][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::set<int, std::less<int>, new_delete_allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.insert(0);
- }
- end[1][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::set<int, std::less<int>, fast_alloc> x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.insert(0);
- }
- end[1][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::set<int, std::less<int>, fast_alloc_sync> x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.insert(0);
- }
- end[1][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
-
- start = std::clock();
- {
- std::list<int, std::allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[2][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::list<int, malloc_allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[2][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::list<int, new_delete_allocator<int> > x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[2][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::list<int, fast_alloc> x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[2][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- start = std::clock();
- {
- std::list<int, fast_alloc_sync> x;
- for (unsigned long i = 0; i < num_ints; ++i)
- x.push_back(0);
- }
- end[2][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
-
- std::cout << "Test 0: Insertion & deletion of " << num_ints << " ints in a vector:" << std::endl;
- std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
- std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
- std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
- std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
- std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
- std::cout << " Pool: not possible" << std::endl;
- std::cout << "Test 1: Insertion & deletion of " << num_ints << " ints in a set:" << std::endl;
- std::cout << " std::allocator: " << end[1][0] << " seconds" << std::endl;
- std::cout << " malloc/free: " << end[1][1] << " seconds" << std::endl;
- std::cout << " new/delete: " << end[1][2] << " seconds" << std::endl;
- std::cout << " Pool Alloc: " << end[1][3] << " seconds" << std::endl;
- std::cout << " Pool /w Sync: " << end[1][4] << " seconds" << std::endl;
- std::cout << " Pool: not possible" << std::endl;
- std::cout << "Test 2: Insertion & deletion of " << num_ints << " ints in a list:" << std::endl;
- std::cout << " std::allocator: " << end[2][0] << " seconds" << std::endl;
- std::cout << " malloc/free: " << end[2][1] << " seconds" << std::endl;
- std::cout << " new/delete: " << end[2][2] << " seconds" << std::endl;
- std::cout << " Pool Alloc: " << end[2][3] << " seconds" << std::endl;
- std::cout << " Pool /w Sync: " << end[2][4] << " seconds" << std::endl;
- std::cout << " Pool: not possible" << std::endl;
-}
-
-int main(int argc, char * argv[])
-{
- if (argc != 1 && argc != 2)
- {
- std::cerr << "Usage: " << argv[0]
- << " [number_of_ints_to_use_each_try]" << std::endl;
- return 1;
- }
-
- errno = 0;
-
- if (argc == 2)
- {
- num_ints = std::strtoul(argv[1], 0, 10);
- if (errno != 0)
- {
- std::cerr << "Cannot convert number \"" << argv[1] << '"' << std::endl;
- return 2;
- }
- }
- else
- num_ints = 700000;
-
- try
- {
- timing_test_containers();
- timing_test_alloc();
- test_number = 5;
- timing_test_alloc_larger<64>();
- test_number = 6;
- timing_test_alloc_larger<256>();
- test_number = 7;
- timing_test_alloc_larger<4096>();
- }
- catch (const std::bad_alloc &)
- {
- std::cerr << "Timing tests ran out of memory; try again with a lower value for number of ints"
- << " (current value is " << num_ints << ")" << std::endl;
- return 3;
- }
- catch (const std::exception & e)
- {
- std::cerr << "Error: " << e.what() << std::endl;
- return 4;
- }
- catch (...)
- {
- std::cerr << "Unknown error" << std::endl;
- return 5;
- }
-
- return 0;
-}
-
-
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk