1
// Copyright (C) 2000, 2001 Stephen Cleary
3
// Distributed under the Boost Software License, Version 1.0. (See
4
// accompanying file LICENSE_1_0.txt or copy at
5
// http://www.boost.org/LICENSE_1_0.txt)
7
// See http://www.boost.org for updates, documentation, and revision history.
9
#ifndef BOOST_SINGLETON_POOL_HPP
10
#define BOOST_SINGLETON_POOL_HPP
14
\brief The <tt>singleton_pool</tt> class allows other pool interfaces
15
for types of the same size to share the same underlying pool.
17
\details Header singleton_pool.hpp provides a template class <tt>singleton_pool</tt>,
18
which provides access to a pool as a singleton object.
22
#include <boost/pool/poolfwd.hpp>
25
#include <boost/pool/pool.hpp>
26
// boost::details::pool::guard
27
#include <boost/pool/detail/guard.hpp>
29
#include <boost/type_traits/aligned_storage.hpp>
34
The singleton_pool class allows other pool interfaces
35
for types of the same size to share the same pool. Template
36
parameters are as follows:
38
<b>Tag</b> User-specified type to uniquely identify this pool: allows different unbounded sets of singleton pools to exist.
40
<b>RequestedSize</b> The size of each chunk returned by member function <tt>malloc()</tt>.
42
<B>UserAllocator</b> User allocator, default = default_user_allocator_new_delete.
44
<b>Mutex</B> This class is the type of mutex to use to protect simultaneous access to the underlying Pool.
45
Can be any Boost.Thread Mutex type or <tt>boost::details::pool::null_mutex</tt>.
46
It is exposed so that users may declare some singleton pools normally (i.e., with synchronization), but
47
some singleton pools without synchronization (by specifying <tt>boost::details::pool::null_mutex</tt>) for efficiency reasons.
48
The member typedef <tt>mutex</tt> exposes the value of this template parameter. The default for this
49
parameter is boost::details::pool::default_mutex which is a synonym for either <tt>boost::details::pool::null_mutex</tt>
50
(when threading support is turned off in the compiler (so BOOST_HAS_THREADS is not set), or threading support
51
has ben explicitly disabled with BOOST_DISABLE_THREADS (Boost-wide disabling of threads) or BOOST_POOL_NO_MT (this library only))
52
or for <tt>boost::mutex</tt> (when threading support is enabled in the compiler).
54
<B>NextSize</b> The value of this parameter is passed to the underlying Pool when it is created and
55
specifies the number of chunks to allocate in the first allocation request (defaults to 32).
56
The member typedef <tt>static const value next_size</tt> exposes the value of this template parameter.
58
<b>MaxSize</B>The value of this parameter is passed to the underlying Pool when it is created and
59
specifies the maximum number of chunks to allocate in any single allocation request (defaults to 0).
63
The underlying pool <i>p</i> referenced by the static functions
64
in singleton_pool is actually declared in a way that is:
66
1 Thread-safe if there is only one thread running before main() begins and after main() ends
67
-- all of the static functions of singleton_pool synchronize their access to p.
69
2 Guaranteed to be constructed before it is used --
70
thus, the simple static object in the synopsis above would actually be an incorrect implementation.
71
The actual implementation to guarantee this is considerably more complicated.
73
3 Note too that a different underlying pool p exists
74
for each different set of template parameters,
75
including implementation-specific ones.
77
4 The underlying pool is constructed "as if" by:
79
pool<UserAllocator> p(RequestedSize, NextSize, MaxSize);
82
The underlying pool constructed by the singleton
83
<b>is never freed</b>. This means that memory allocated
84
by a singleton_pool can be still used after main() has
85
completed, but may mean that some memory checking programs
86
will complain about leaks from singleton_pool.
90
template <typename Tag,
91
unsigned RequestedSize,
92
typename UserAllocator,
99
typedef Tag tag; /*!< The Tag template parameter uniquely
100
identifies this pool and allows
101
different unbounded sets of singleton pools to exist.
102
For example, the pool allocators use two tag classes to ensure that the
103
two different allocator types never share the same underlying singleton pool.
104
Tag is never actually used by singleton_pool.
106
typedef Mutex mutex; //!< The type of mutex used to synchonise access to this pool (default <tt>details::pool::default_mutex</tt>).
107
typedef UserAllocator user_allocator; //!< The user-allocator used by this pool, default = <tt>default_user_allocator_new_delete</tt>.
108
typedef typename pool<UserAllocator>::size_type size_type; //!< size_type of user allocator.
109
typedef typename pool<UserAllocator>::difference_type difference_type; //!< difference_type of user allocator.
111
BOOST_STATIC_CONSTANT(unsigned, requested_size = RequestedSize); //!< The size of each chunk allocated by this pool.
112
BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize); //!< The number of chunks to allocate on the first allocation.
117
#ifndef BOOST_DOXYGEN
118
struct pool_type: public Mutex, public pool<UserAllocator>
120
pool_type() : pool<UserAllocator>(RequestedSize, NextSize, MaxSize) {}
121
}; // struct pool_type: Mutex
125
// This is invoked when we build with Doxygen only:
128
static pool<UserAllocator> p; //!< For exposition only!
133
static void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
134
{ //! Equivalent to SingletonPool::p.malloc(); synchronized.
135
pool_type & p = get_pool();
136
details::pool::guard<Mutex> g(p);
139
static void * ordered_malloc()
140
{ //! Equivalent to SingletonPool::p.ordered_malloc(); synchronized.
141
pool_type & p = get_pool();
142
details::pool::guard<Mutex> g(p);
143
return p.ordered_malloc();
145
static void * ordered_malloc(const size_type n)
146
{ //! Equivalent to SingletonPool::p.ordered_malloc(n); synchronized.
147
pool_type & p = get_pool();
148
details::pool::guard<Mutex> g(p);
149
return p.ordered_malloc(n);
151
static bool is_from(void * const ptr)
152
{ //! Equivalent to SingletonPool::p.is_from(chunk); synchronized.
153
//! \returns true if chunk is from SingletonPool::is_from(chunk)
154
pool_type & p = get_pool();
155
details::pool::guard<Mutex> g(p);
156
return p.is_from(ptr);
158
static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr)
159
{ //! Equivalent to SingletonPool::p.free(chunk); synchronized.
160
pool_type & p = get_pool();
161
details::pool::guard<Mutex> g(p);
164
static void ordered_free(void * const ptr)
165
{ //! Equivalent to SingletonPool::p.ordered_free(chunk); synchronized.
166
pool_type & p = get_pool();
167
details::pool::guard<Mutex> g(p);
170
static void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const ptr, const size_type n)
171
{ //! Equivalent to SingletonPool::p.free(chunk, n); synchronized.
172
pool_type & p = get_pool();
173
details::pool::guard<Mutex> g(p);
176
static void ordered_free(void * const ptr, const size_type n)
177
{ //! Equivalent to SingletonPool::p.ordered_free(chunk, n); synchronized.
178
pool_type & p = get_pool();
179
details::pool::guard<Mutex> g(p);
180
p.ordered_free(ptr, n);
182
static bool release_memory()
183
{ //! Equivalent to SingletonPool::p.release_memory(); synchronized.
184
pool_type & p = get_pool();
185
details::pool::guard<Mutex> g(p);
186
return p.release_memory();
188
static bool purge_memory()
189
{ //! Equivalent to SingletonPool::p.purge_memory(); synchronized.
190
pool_type & p = get_pool();
191
details::pool::guard<Mutex> g(p);
192
return p.purge_memory();
196
typedef boost::aligned_storage<sizeof(pool_type), boost::alignment_of<pool_type>::value> storage_type;
197
static storage_type storage;
199
static pool_type& get_pool()
201
static bool f = false;
204
// This code *must* be called before main() starts,
205
// and when only one thread is executing.
207
new (&storage) pool_type;
210
// The following line does nothing else than force the instantiation
211
// of singleton<T>::create_object, whose constructor is
212
// called before main() begins.
213
create_object.do_nothing();
215
return *static_cast<pool_type*>(static_cast<void*>(&storage));
218
struct object_creator
221
{ // This constructor does nothing more than ensure that instance()
222
// is called before main() begins, thus creating the static
223
// T object before multithreading race issues can come up.
224
singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::get_pool();
226
inline void do_nothing() const
230
static object_creator create_object;
231
}; // struct singleton_pool
233
template <typename Tag,
234
unsigned RequestedSize,
235
typename UserAllocator,
239
typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage_type singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage;
241
template <typename Tag,
242
unsigned RequestedSize,
243
typename UserAllocator,
247
typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::object_creator singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::create_object;