Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73121 - in sandbox/guild/pool: boost/pool boost/pool/detail libs/pool/doc libs/pool/example libs/pool/test
From: john_at_[hidden]
Date: 2011-07-15 13:40:51


Author: johnmaddock
Date: 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
New Revision: 73121
URL: http://svn.boost.org/trac/boost/changeset/73121

Log:
Add some debugging code.
Add tentative Valgrind support.
Change singleton usage to address issue 5526 by making singletons eternal.
Add Valgrind tests.
Update docs to match.
Refs #5526.
Added:
   sandbox/guild/pool/libs/pool/test/test_bug_5526.cpp (contents, props changed)
   sandbox/guild/pool/libs/pool/test/test_valgrind_fail_1.cpp (contents, props changed)
   sandbox/guild/pool/libs/pool/test/test_valgrind_fail_2.cpp (contents, props changed)
Removed:
   sandbox/guild/pool/boost/pool/detail/singleton.hpp
Text files modified:
   sandbox/guild/pool/boost/pool/object_pool.hpp | 9 ++
   sandbox/guild/pool/boost/pool/pool.hpp | 131 +++++++++++++++++++++++++++++++++++++++
   sandbox/guild/pool/boost/pool/pool_alloc.hpp | 21 ++++++
   sandbox/guild/pool/boost/pool/simple_segregated_storage.hpp | 40 +++++++++++
   sandbox/guild/pool/boost/pool/singleton_pool.hpp | 123 +++++++++++++++++++++++++++---------
   sandbox/guild/pool/libs/pool/doc/jamfile.v2 | 57 +++++-----------
   sandbox/guild/pool/libs/pool/doc/pool.qbk | 98 ++++++++++-------------------
   sandbox/guild/pool/libs/pool/example/time_pool_alloc.cpp | 4 +
   sandbox/guild/pool/libs/pool/test/Jamfile.v2 | 20 +++++
   sandbox/guild/pool/libs/pool/test/test_bug_2696.cpp | 4 +
   10 files changed, 367 insertions(+), 140 deletions(-)

Deleted: sandbox/guild/pool/boost/pool/detail/singleton.hpp
==============================================================================
--- sandbox/guild/pool/boost/pool/detail/singleton.hpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
+++ (empty file)
@@ -1,131 +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
-
-/*!
-\file
-\brief Access to a Singleton of a class type.
-detail/singleton.hpp provides a way to access a Singleton of a class type.
-This is not a general Singleton solution!
-It is restricted in that the class type must have a default constructor.
-\details
- Guarantees\n
- The singleton instance is guaranteed to be constructed before main() begins,
- and destructed after main() ends.
- Furthermore, it is guaranteed to be constructed before
- the first call to singleton_default<T>::instance() is complete
- (even if called before main() begins).
- Thus, if there are not multiple threads running except within main(),
- and if all access to the singleton is restricted by mutexes,
- then this guarantee allows a thread-safe singleton.
-
- 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.
-*/
-
-// The following code might be put into some Boost.Config header in a later revision.
-#ifdef __BORLANDC__
-# pragma option push -w-inl
-#endif
-
-namespace boost {
-
-namespace details {
-namespace pool {
-
-// T must be: no-throw default constructible and no-throw destructible.
-template <typename T>
-/*!< \tparam T type which must be a singleton.
-\pre T must be no-throw default constructible and no-throw destructible.
-*/
-struct singleton_default
-{
- private:
- 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_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()
- { //! \returns a reference of type T& to the singleton 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: sandbox/guild/pool/boost/pool/object_pool.hpp
==============================================================================
--- sandbox/guild/pool/boost/pool/object_pool.hpp (original)
+++ sandbox/guild/pool/boost/pool/object_pool.hpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -219,6 +219,7 @@
 template <typename T, typename UserAllocator>
 object_pool<T, UserAllocator>::~object_pool()
 {
+#ifndef BOOST_POOL_VALGRIND
   // handle trivial case of invalid list.
   if (!this->list.valid())
     return;
@@ -266,6 +267,14 @@
   // Make the block list empty so that the inherited destructor doesn't try to
   // 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: sandbox/guild/pool/boost/pool/pool.hpp
==============================================================================
--- sandbox/guild/pool/boost/pool/pool.hpp (original)
+++ sandbox/guild/pool/boost/pool/pool.hpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -39,6 +39,10 @@
 #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; }
@@ -233,6 +237,7 @@
 }; // class PODptr
 } // namespace details
 
+#ifndef BOOST_POOL_VALGRIND
 /*!
   \brief A fast memory allocator that guarantees proper alignment of all allocated chunks.
 
@@ -420,7 +425,6 @@
       //! 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)();
@@ -431,7 +435,6 @@
     { //! 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)();
@@ -880,6 +883,130 @@
   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:
+ unsigned chunk_size, max_alloc_size;
+ std::set<void*> free_list, used_list;
+};
+
+#endif
+
 } // namespace boost
 
 #ifdef BOOST_MSVC

Modified: sandbox/guild/pool/boost/pool/pool_alloc.hpp
==============================================================================
--- sandbox/guild/pool/boost/pool/pool_alloc.hpp (original)
+++ sandbox/guild/pool/boost/pool/pool_alloc.hpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -125,7 +125,17 @@
   <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,
@@ -304,6 +314,15 @@
   <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,

Modified: sandbox/guild/pool/boost/pool/simple_segregated_storage.hpp
==============================================================================
--- sandbox/guild/pool/boost/pool/simple_segregated_storage.hpp (original)
+++ sandbox/guild/pool/boost/pool/simple_segregated_storage.hpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -31,6 +31,12 @@
 #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 {
 
 /*!
@@ -106,8 +112,9 @@
       //! 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'
@@ -118,7 +125,7 @@
       //! 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);
 
@@ -127,6 +134,7 @@
         add_block(block, nsz, npartition_sz);
       else
         nextof(loc) = segregate(block, nsz, npartition_sz, nextof(loc));
+ BOOST_POOL_VALIDATE_INTERNALS
     }
 
     // default destructor.
@@ -140,10 +148,12 @@
     { //! 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.
       first = nextof(first);
+ BOOST_POOL_VALIDATE_INTERNALS
       return ret;
     }
 
@@ -151,8 +161,10 @@
     { //! 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
     }
 
     void ordered_free(void * const chunk)
@@ -162,6 +174,7 @@
       //! \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.
@@ -172,6 +185,7 @@
         nextof(chunk) = nextof(loc);
         nextof(loc) = chunk;
       }
+ BOOST_POOL_VALIDATE_INTERNALS
     }
 
    void * malloc_n(size_type n, size_type partition_size);
@@ -184,8 +198,10 @@
     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
@@ -198,10 +214,26 @@
       //! 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",
@@ -319,6 +351,7 @@
 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;
@@ -331,6 +364,7 @@
   } while (iter == 0);
   void * const ret = nextof(start);
   nextof(start) = nextof(iter);
+ BOOST_POOL_VALIDATE_INTERNALS
   return ret;
 }
 

Modified: sandbox/guild/pool/boost/pool/singleton_pool.hpp
==============================================================================
--- sandbox/guild/pool/boost/pool/singleton_pool.hpp (original)
+++ sandbox/guild/pool/boost/pool/singleton_pool.hpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -23,11 +23,11 @@
 
 // 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 {
 
  /*!
@@ -42,10 +42,14 @@
  <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>details::pool::null_mutex</tt>) for efficiency reasons.
+ 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 details::pool::default_mutex.
+ 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).
@@ -73,6 +77,14 @@
   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,
@@ -103,17 +115,11 @@
     singleton_pool();
 
 #ifndef BOOST_DOXYGEN
- struct pool_type: Mutex
+ struct pool_type: public Mutex, public pool<UserAllocator>
     {
- pool<UserAllocator> p;
- pool_type()
- :
- p(RequestedSize, NextSize)
- {
- }
+ pool_type() : pool<UserAllocator>(RequestedSize, NextSize) {}
     }; // struct pool_type: Mutex
 
- typedef details::pool::singleton_default<pool_type> singleton;
 #else
     //
     // This is invoked when we build with Doxygen only:
@@ -126,67 +132,120 @@
   public:
     static void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
     { //! Equivalent to SingletonPool::p.malloc(); synchronized.
- pool_type & p = singleton::instance();
+ pool_type & p = get_pool();
       details::pool::guard<Mutex> g(p);
- return (p.p.malloc)();
+ return (p.malloc)();
     }
     static void * ordered_malloc()
     { //! Equivalent to SingletonPool::p.ordered_malloc(); synchronized.
- pool_type & p = singleton::instance();
+ 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)
     { //! Equivalent to SingletonPool::p.ordered_malloc(n); synchronized.
- pool_type & p = singleton::instance();
+ 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)
     { //! Equivalent to SingletonPool::p.is_from(chunk); synchronized.
       //! \returns true if chunk is from SingletonPool::is_from(chunk)
- pool_type & p = singleton::instance();
+ 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)
     { //! Equivalent to SingletonPool::p.free(chunk); synchronized.
- pool_type & p = singleton::instance();
+ 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)
     { //! Equivalent to SingletonPool::p.ordered_free(chunk); synchronized.
- pool_type & p = singleton::instance();
+ 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)
     { //! Equivalent to SingletonPool::p.free(chunk, n); synchronized.
- pool_type & p = singleton::instance();
+ 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)
     { //! Equivalent to SingletonPool::p.ordered_free(chunk, n); synchronized.
- pool_type & p = singleton::instance();
+ 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()
     { //! Equivalent to SingletonPool::p.release_memory(); synchronized.
- pool_type & p = singleton::instance();
+ pool_type & p = get_pool();
       details::pool::guard<Mutex> g(p);
- return p.p.release_memory();
+ return p.release_memory();
     }
     static bool purge_memory()
     { //! Equivalent to SingletonPool::p.purge_memory(); synchronized.
- pool_type & p = singleton::instance();
+ 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
 
 #endif

Modified: sandbox/guild/pool/libs/pool/doc/jamfile.v2
==============================================================================
--- sandbox/guild/pool/libs/pool/doc/jamfile.v2 (original)
+++ sandbox/guild/pool/libs/pool/doc/jamfile.v2 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -7,47 +7,12 @@
 #
 # See http://www.boost.org for updates, documentation, and revision history.
 
+path-constant boost-root : [ modules.peek : BOOST ] ;
 path-constant nav_images : html/images/ ; # png and svg images for home, next, note, tip...
 path-constant images_location : html ; # location of SVG and PNG images referenced by Quickbook.
 
-echo "images_location" $(images_location) ; # \guild\pool\libs\pool\doc\html
-echo "nav_images" $(nav_images) ; # \guild\pool\libs\pool\doc\html\images
-
 import modules ;
 
-if --enable-index in [ modules.peek : ARGV ]
-{
- ECHO "Building the Pool docs with automatic index generation enabled." ;
- using auto-index ;
- project : requirements
- # <auto-index>on turns on index (or off).
- <auto-index>on
-
- # Choose indexing method (separately for html and pdf):
- <format>html:<auto-index-internal>on # on (or off) to use internally generated indexes.
- # <format>html:<xsl:param>generate.index=0 # Don't let the XSL stylesheets generate indexes.
-
- <format>pdf:<auto-index-internal>off # on (or off) to use internally generated indexes.
- # <auto-index-type>index # Use <index>...</index> as the XML wrapper.
-
- <format>pdf:<xsl:param>index.on.type=1 # For the native stylesheets to generate the different indexes.
- # PDF native index support is probably better for PDFs as then you actually get page numbers.
-
- <auto-index-script>index.idx # Specifies the name of the script to load.
- # <auto-index-prefix>../../../ # Path to /pool so index.idx !scan-path can use boost/ and libs/doc.
- <auto-index-prefix>../../..
-
- <quickbook-define>enable_index
-
- # <auto-index-verbose>on
-
- ;
-}
-else
-{
- ECHO "Building the Pool docs with automatic index generation disabled. To get an auto-index, try building with --enable-index." ;
-}
-
 using doxygen ; # Required if you want to use Doxygen.
 using quickbook ;
 
@@ -78,7 +43,7 @@
                         <xsl:param>"boost.doxygen.reftitle=Boost.Pool C++ Reference"
    ;
 
-xml pool : pool.qbk ;
+xml pool : pool.qbk : <include>$(boost-root)/tools/auto_index/include ;
 
 boostbook standalone
    :
@@ -167,6 +132,23 @@
       <format>pdf:<xsl:param>draft.mode="no"
       <format>pdf:<xsl:param>boost.url.prefix=I:/boost-sandbox/guild/pool/libs/pool/doc/html
                 
+ # <auto-index>on turns on index (or off).
+ <auto-index>on
+
+ # Choose indexing method (separately for html and pdf):
+ <format>html:<auto-index-internal>on # on (or off) to use internally generated indexes.
+ # <format>html:<xsl:param>generate.index=0 # Don't let the XSL stylesheets generate indexes.
+
+ <format>pdf:<auto-index-internal>off # on (or off) to use internally generated indexes.
+ # <auto-index-type>index # Use <index>...</index> as the XML wrapper.
+
+ <format>pdf:<xsl:param>index.on.type=1 # For the native stylesheets to generate the different indexes.
+ # PDF native index support is probably better for PDFs as then you actually get page numbers.
+
+ <auto-index-script>index.idx # Specifies the name of the script to load.
+ # <auto-index-prefix>../../../ # Path to /pool so index.idx !scan-path can use boost/ and libs/doc.
+ <auto-index-prefix>../../..
+
       <dependency>autodoc #
       <dependency>css-install
       <dependency>png-install
@@ -175,7 +157,6 @@
       <dependency>pool-svg-install
    ;
 
-path-constant boost-root : [ modules.peek : BOOST ] ;
 install css-install : $(boost-root)/doc/src/boostbook.css : <location>html ;
 
 install png-install : [ glob $(boost-root)/doc/src/images/*.png $(boost-root)/boost.png ] : <location>html/images ;

Modified: sandbox/guild/pool/libs/pool/doc/pool.qbk
==============================================================================
--- sandbox/guild/pool/libs/pool/doc/pool.qbk (original)
+++ sandbox/guild/pool/libs/pool/doc/pool.qbk 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -61,7 +61,7 @@
 </inlinemediaobject>
 ''']
 
-[section:pool Boost Pool Library]
+[section:pool Introduction and Overview]
 
 [section:conventions Documentation Naming and Formatting Conventions]
 
@@ -1033,7 +1033,7 @@
 [endsect][/section:user_allocator The UserAllocator Concept]
 [endsect] [/section:pooling Pool in more depth]
 
-[xinclude autodoc.xml] [/ Boost.Pool Reference section, using Doxygen reference documentation.]
+[endsect]
 
 [/Note that there will be always some warnings about the .ipp files in Doxygen warnings and Autodoxywarnings.log files.
 "Warning: include file boost/pool/detail/pool_construct.ipp not found, perhaps you forgot to add its directory to INCLUDE_PATH?"
@@ -1057,17 +1057,19 @@
 
 ]
 
-[endsect] [/section:pool Boost Pool Library]
+[xinclude autodoc.xml] [/ Boost.Pool Reference section, using Doxygen reference documentation.]
+
+
+[/section:pool Introduction/Overview]
 
 [section:appendices Appendices]
 
 [section:history Appendix A: History]
 
-[section [*Version 1.0.0, January 1, 2000] ['First release]]
+[h4 Version 2.0.0, January 11, 2011]
 
-[endsect] [/section [*Version 1.0.0, January 1, 2000] ['First release]]
+['Documentation and testing revision]
 
-[section [*Version 2.0.0, January 11, 2011] ['Documentation and testing revision]]
 [*Features:]
 
 * Fix issues
@@ -1086,25 +1088,13 @@
 to My Style Sheet. Html pages are now displayed as Quickbook and can be copied and pasted
 into quickbook files using your favored text editor for Quickbook.
 
-[endsect] [/section [*Version 2.0.0, January 11, 2011] ['Documentation and testing revision]]
-
-[endsect] [/section:history Appendix A: History]
-
-[section:rationale Appendix B: Rationale]
-
-TODO.
-
-[endsect] [/section:rationale Appendix B: Rationale]
+[h4 Version 1.0.0, January 1, 2000]
 
+['First release]
 
-[section:implementation Appendix C: Implementation Notes]
-
-TODO.
-
-[endsect] [/section:implementation Appendix C: Implementation Notes]
-
+[endsect] [/section:history Appendix A: History]
 
-[section:faq Appendix D: FAQ]
+[section:faq Appendix B: FAQ]
 
 [h5 Why should I use Pool?]
 
@@ -1122,28 +1112,33 @@
 
 In general, use Pools when you need a more efficient way to do unusual memory control.
 
-[endsect] [/section:faq Appendix D: FAQ]
+[endsect] [/section:faq Appendix B: FAQ]
 
-[section:acknowledgements Appendix E: Acknowledgements]
+[section:acknowledgements Appendix C: Acknowledgements]
 
 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!
 
-[endsect] [/section:acknowledgements Appendix E: Acknowledgements]
+[endsect] [/section:acknowledgements Appendix C: Acknowledgements]
 
-[section:tests Appendix F: Tests]
+[section:tests Appendix D: Tests]
 
 See folder `boost/libs/pool/test/`.
 
-[endsect] [/section:tests Appendix F: Tests]
+[endsect] [/section:tests Appendix D: Tests]
 
-[section:tickets Appendix G: Tickets]
+[section:tickets Appendix E: Tickets]
 
 Report and view bugs and features by adding a ticket at [@https://svn.boost.org/trac/boost Boost.Trac].
 
-[endsect] [/section:tickets Appendix G: Tickets]
+Existing open tickets for this library alone can be viewed
+[@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=pool&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority here].
+Existing tickets for this library - including closed ones - can be viewed
+[@https://svn.boost.org/trac/boost/query?status=assigned&status=closed&status=new&status=reopened&component=pool&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority here].
+
+[endsect] [/section:tickets Appendix E: Tickets]
 
-[section:implementations Appendix H: Other Implementations]
+[section:implementations Appendix F: Other Implementations]
 
 Pool allocators are found in many programming languages, and in many variations.
 The beginnings of many implementations may be found in common programming literature;
@@ -1173,9 +1168,9 @@
   * Not thread-safe.
   * The static pooling example is not portable.
 
-[endsect] [/section:implementations Appendix H: Other Implementations]
+[endsect] [/section:implementations Appendix F: Other Implementations]
 
-[section:references Appendix I: References]
+[section:references Appendix G: References]
 
 # [#ref1] Doug Lea, A Memory Allocator. See [@http://gee.cs.oswego.edu/dl/html/malloc.html http://gee.cs.oswego.edu/dl/html/malloc.html]
 # [#ref2]Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,
@@ -1183,49 +1178,26 @@
 in International Workshop on Memory Management, September 1995, pg. 28, 36.
 See [@ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps]
 
-[endsect] [/section:references Appendix I: references]
+[endsect] [/section:references Appendix G: references]
 
-[section:todo Appendix J: Future plans]
+[section:todo Appendix H: Future plans]
 
 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.
 
-Many functions need better Doxygen comments about their function. (rebind in particular is undocumented).
-
-These comments appear in the reference section.
-
-[endsect] [/section:todo Appendix J: Future plans]
+[endsect] [/section:todo Appendix G: Future plans]
 
 [endsect] [/section:appendices Appendices]
 
 [section:indexes Indexes]
 
-[? enable_index
-'''
- <index/>
-
- <index type="function_name">
- <title>Function Index</title>
- </index>
-
- <index type="class_name">
- <title>Class Index</title>
- </index>
-
- <index type="typedef_name">
- <title>Typedef Index</title>
- </index>
-'''
-]
+[include auto_index_helpers.qbk]
 
-[/ BOOST_PREVENT_MACRO_SUBSTITUTION is the only macro and not sure if useful to show here?
- but after removing still get BOOST_PREVENT_MACRO_SUBSTITUTION in the function index.
- <index type="macro_name">
- <title>Macro Index</title>
- </index>
- <index/>
-]
+[named_index function_name Function Index]
+[named_index class_name Class Index]
+[named_index typedef_name Typedef Index]
+[index]
 
 [endsect] [/section:indexes Indexes]

Modified: sandbox/guild/pool/libs/pool/example/time_pool_alloc.cpp
==============================================================================
--- sandbox/guild/pool/libs/pool/example/time_pool_alloc.cpp (original)
+++ sandbox/guild/pool/libs/pool/example/time_pool_alloc.cpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -449,6 +449,10 @@
   else
     num_ints = 700000;
 
+#ifndef _NDEBUG
+ num_ints /= 100;
+#endif
+
   try
   {
     timing_test_containers();

Modified: sandbox/guild/pool/libs/pool/test/Jamfile.v2
==============================================================================
--- sandbox/guild/pool/libs/pool/test/Jamfile.v2 (original)
+++ sandbox/guild/pool/libs/pool/test/Jamfile.v2 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -32,6 +32,7 @@
     [ run test_bug_4960.cpp ]
     [ run test_bug_1252.cpp ]
     [ run test_bug_2696.cpp ]
+ [ run test_bug_5526.cpp ]
     [ run ../example/time_pool_alloc.cpp ]
     [ compile test_poisoned_macros.cpp ]
 
@@ -47,6 +48,23 @@
     [ 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 ]
 
+#
+# 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_gcd_lcm.cpp : : : <define>BOOST_POOL_VALGRIND=1 [ check-target-builds valgrind_config_check : <testing.launcher>"valgrind --error-exitcode=1" : <build>no ] : test_gcd_lcm_valgrind_2 ]
+ [ 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-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 ] ]
+ ;
 

Modified: sandbox/guild/pool/libs/pool/test/test_bug_2696.cpp
==============================================================================
--- sandbox/guild/pool/libs/pool/test/test_bug_2696.cpp (original)
+++ sandbox/guild/pool/libs/pool/test/test_bug_2696.cpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -17,7 +17,11 @@
 
    static char * malloc BOOST_PREVENT_MACRO_SUBSTITUTION(const size_type bytes)
    {
+#ifndef BOOST_POOL_VALGRIND
       static const unsigned max_size = 4 * 40 + sizeof(void*) + 2 * sizeof(std::size_t);
+#else
+ static const unsigned max_size = 4 * 40;
+#endif
       if(bytes > max_size)
          return 0;
       return new (std::nothrow) char[bytes];

Added: sandbox/guild/pool/libs/pool/test/test_bug_5526.cpp
==============================================================================
--- (empty file)
+++ sandbox/guild/pool/libs/pool/test/test_bug_5526.cpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -0,0 +1,35 @@
+/* Copyright (C) 2011 John Maddock
+*
+* 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)
+*/
+
+// Test of bug #2656 (https://svn.boost.org/trac/boost/ticket/2526)
+
+#include <boost/pool/pool.hpp>
+#include <boost/pool/singleton_pool.hpp>
+#include <boost/assert.hpp>
+
+struct bad
+{
+ bad()
+ {
+ buf = static_cast<int*>(boost::singleton_pool<int, sizeof(int)>::malloc());
+ *buf = 0x1234;
+ }
+ ~bad()
+ {
+ BOOST_ASSERT(*buf == 0x1234);
+ boost::singleton_pool<int, sizeof(int)>::free(buf);
+ }
+ int* buf;
+};
+
+std::auto_ptr<bad> ptr;
+
+int main()
+{
+ ptr.reset(new bad());
+ return 0;
+}

Added: sandbox/guild/pool/libs/pool/test/test_valgrind_fail_1.cpp
==============================================================================
--- (empty file)
+++ sandbox/guild/pool/libs/pool/test/test_valgrind_fail_1.cpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -0,0 +1,22 @@
+/* Copyright (C) 2011 John Maddock
+*
+* 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)
+*/
+
+// Test of bug #2656 (https://svn.boost.org/trac/boost/ticket/2656)
+
+#include <boost/pool/pool.hpp>
+#include <iostream>
+#include <iomanip>
+
+static const int magic_value = 0x12345678;
+
+int main()
+{
+ boost::pool<> p(sizeof(int));
+ int* ptr = static_cast<int*>((p.malloc)());
+ std::cout << *ptr << std::endl; // uninitialized read
+ return 0;
+}

Added: sandbox/guild/pool/libs/pool/test/test_valgrind_fail_2.cpp
==============================================================================
--- (empty file)
+++ sandbox/guild/pool/libs/pool/test/test_valgrind_fail_2.cpp 2011-07-15 13:40:49 EDT (Fri, 15 Jul 2011)
@@ -0,0 +1,20 @@
+/* Copyright (C) 2011 John Maddock
+*
+* 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)
+*/
+
+// Test of bug #2656 (https://svn.boost.org/trac/boost/ticket/2656)
+
+#include <boost/pool/pool.hpp>
+
+int main()
+{
+ boost::pool<> p(sizeof(int));
+ int* ptr = static_cast<int*>((p.malloc)());
+ *ptr = 0;
+ (p.free)(ptr);
+ *ptr = 2; // write to freed memory
+ 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