~ubuntu-branches/debian/sid/boost1.49/sid

« back to all changes in this revision

Viewing changes to boost/pool/singleton_pool.hpp

  • Committer: Package Import Robot
  • Author(s): Steve M. Robbins
  • Date: 2012-02-26 00:31:44 UTC
  • Revision ID: package-import@ubuntu.com-20120226003144-eaytp12cbf6ubpms
Tags: upstream-1.49.0
ImportĀ upstreamĀ versionĀ 1.49.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2000, 2001 Stephen Cleary
 
2
//
 
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)
 
6
//
 
7
// See http://www.boost.org for updates, documentation, and revision history.
 
8
 
 
9
#ifndef BOOST_SINGLETON_POOL_HPP
 
10
#define BOOST_SINGLETON_POOL_HPP
 
11
 
 
12
/*!
 
13
  \file
 
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.
 
16
 
 
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.
 
19
  
 
20
*/
 
21
 
 
22
#include <boost/pool/poolfwd.hpp>
 
23
 
 
24
// boost::pool
 
25
#include <boost/pool/pool.hpp>
 
26
// boost::details::pool::guard
 
27
#include <boost/pool/detail/guard.hpp>
 
28
 
 
29
#include <boost/type_traits/aligned_storage.hpp>
 
30
 
 
31
namespace boost {
 
32
 
 
33
 /*! 
 
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:
 
37
 
 
38
 <b>Tag</b> User-specified type to uniquely identify this pool: allows different unbounded sets of singleton pools to exist.
 
39
 
 
40
 <b>RequestedSize</b> The size of each chunk returned by member function <tt>malloc()</tt>.
 
41
 
 
42
 <B>UserAllocator</b> User allocator, default = default_user_allocator_new_delete.
 
43
 
 
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).
 
53
 
 
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.
 
57
 
 
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).
 
60
 
 
61
  <b>Notes:</b>
 
62
 
 
63
  The underlying pool <i>p</i> referenced by the static functions
 
64
  in singleton_pool is actually declared in a way that is:
 
65
 
 
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.
 
68
 
 
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.
 
72
 
 
73
  3 Note too that a different underlying pool p exists
 
74
  for each different set of template parameters,
 
75
  including implementation-specific ones.
 
76
 
 
77
  4 The underlying pool is constructed "as if" by:
 
78
 
 
79
  pool<UserAllocator> p(RequestedSize, NextSize, MaxSize);
 
80
 
 
81
  \attention
 
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.
 
87
 
 
88
  */
 
89
 
 
90
 template <typename Tag,
 
91
    unsigned RequestedSize,
 
92
    typename UserAllocator,
 
93
    typename Mutex,
 
94
    unsigned NextSize,
 
95
    unsigned MaxSize >
 
96
class singleton_pool
 
97
{
 
98
  public:
 
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.
 
105
    */
 
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.
 
110
 
 
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.
 
113
 
 
114
private:
 
115
    singleton_pool();
 
116
 
 
117
#ifndef BOOST_DOXYGEN
 
118
    struct pool_type: public Mutex, public pool<UserAllocator>
 
119
    {
 
120
      pool_type() : pool<UserAllocator>(RequestedSize, NextSize, MaxSize) {}
 
121
    }; //  struct pool_type: Mutex
 
122
 
 
123
#else
 
124
    //
 
125
    // This is invoked when we build with Doxygen only:
 
126
    //
 
127
public:
 
128
    static pool<UserAllocator> p; //!< For exposition only!
 
129
#endif
 
130
 
 
131
 
 
132
  public:
 
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);
 
137
      return (p.malloc)();
 
138
    }
 
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();
 
144
    }
 
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);
 
150
    }
 
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);
 
157
    }
 
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);
 
162
      (p.free)(ptr);
 
163
    }
 
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);
 
168
      p.ordered_free(ptr);
 
169
    }
 
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);
 
174
      (p.free)(ptr, n);
 
175
    }
 
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);
 
181
    }
 
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();
 
187
    }
 
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();
 
193
    }
 
194
 
 
195
private:
 
196
   typedef boost::aligned_storage<sizeof(pool_type), boost::alignment_of<pool_type>::value> storage_type;
 
197
   static storage_type storage;
 
198
 
 
199
   static pool_type& get_pool()
 
200
   {
 
201
      static bool f = false;
 
202
      if(!f)
 
203
      {
 
204
         // This code *must* be called before main() starts, 
 
205
         // and when only one thread is executing.
 
206
         f = true;
 
207
         new (&storage) pool_type;
 
208
      }
 
209
 
 
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();
 
214
 
 
215
      return *static_cast<pool_type*>(static_cast<void*>(&storage));
 
216
   }
 
217
 
 
218
   struct object_creator
 
219
   {
 
220
      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();
 
225
      }
 
226
      inline void do_nothing() const
 
227
      {
 
228
      }
 
229
   };
 
230
   static object_creator create_object;
 
231
}; // struct singleton_pool
 
232
 
 
233
template <typename Tag,
 
234
    unsigned RequestedSize,
 
235
    typename UserAllocator,
 
236
    typename Mutex,
 
237
    unsigned NextSize,
 
238
    unsigned MaxSize >
 
239
typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage_type singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::storage;
 
240
 
 
241
template <typename Tag,
 
242
    unsigned RequestedSize,
 
243
    typename UserAllocator,
 
244
    typename Mutex,
 
245
    unsigned NextSize,
 
246
    unsigned MaxSize >
 
247
typename singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::object_creator singleton_pool<Tag, RequestedSize, UserAllocator, Mutex, NextSize, MaxSize>::create_object;
 
248
 
 
249
} // namespace boost
 
250
 
 
251
#endif