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_OBJECT_POOL_HPP
10 #define BOOST_OBJECT_POOL_HPP
11
12 #include <boost/pool/poolfwd.hpp>
13
14 // boost::pool
15 #include <boost/pool/pool.hpp>
16
17 // The following code will be put into Boost.Config in a later revision
18 #if defined(BOOST_MSVC) || defined(__KCC)
19 # define BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
20 #endif
21
22 // The following code might be put into some Boost.Config header in a later revision
23 #ifdef __BORLANDC__
24 # pragma option push -w-inl
25 #endif
26
27 // There are a few places in this file where the expression "this->m" is used.
28 // This expression is used to force instantiation-time name lookup, which I am
29 // informed is required for strict Standard compliance. It's only necessary
30 // if "m" is a member of a base class that is dependent on a template
31 // parameter.
32 // Thanks to Jens Maurer for pointing this out!
33
34 namespace boost {
35
36 // T must have a non-throwing destructor
37 template <typename T, typename UserAllocator>
38 class object_pool: protected pool<UserAllocator>
39 {
40 public:
41 typedef T element_type;
42 typedef UserAllocator user_allocator;
43 typedef typename pool<UserAllocator>::size_type size_type;
44 typedef typename pool<UserAllocator>::difference_type difference_type;
45
46 protected:
store()47 pool<UserAllocator> & store() { return *this; }
store() const48 const pool<UserAllocator> & store() const { return *this; }
49
50 // for the sake of code readability :)
nextof(void * const ptr)51 static void * & nextof(void * const ptr)
52 { return *(static_cast<void **>(ptr)); }
53
54 public:
55 // This constructor parameter is an extension!
object_pool(const size_type next_size=32,const size_type max_size=0)56 explicit object_pool(const size_type next_size = 32, const size_type max_size = 0)
57 :pool<UserAllocator>(sizeof(T), next_size, max_size) { }
58
59 ~object_pool();
60
61 // Returns 0 if out-of-memory
BOOST_PREVENT_MACRO_SUBSTITUTION()62 element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
63 { return static_cast<element_type *>(store().ordered_malloc()); }
BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)64 void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)
65 { store().ordered_free(chunk); }
is_from(element_type * const chunk) const66 bool is_from(element_type * const chunk) const
67 { return store().is_from(chunk); }
68
construct()69 element_type * construct()
70 {
71 element_type * const ret = (malloc)();
72 if (ret == 0)
73 return ret;
74 try { new (ret) element_type(); }
75 catch (...) { (free)(ret); throw; }
76 return ret;
77 }
78
79 // Include automatically-generated file for family of template construct()
80 // functions
81 #ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
82 # include <boost/pool/detail/pool_construct.inc>
83 #else
84 # include <boost/pool/detail/pool_construct_simple.inc>
85 #endif
86
destroy(element_type * const chunk)87 void destroy(element_type * const chunk)
88 {
89 chunk->~T();
90 (free)(chunk);
91 }
92
93 // These functions are extensions!
get_next_size() const94 size_type get_next_size() const { return store().get_next_size(); }
set_next_size(const size_type x)95 void set_next_size(const size_type x) { store().set_next_size(x); }
96 };
97
98 template <typename T, typename UserAllocator>
~object_pool()99 object_pool<T, UserAllocator>::~object_pool()
100 {
101 // handle trivial case
102 if (!this->list.valid())
103 return;
104
105 details::PODptr<size_type> iter = this->list;
106 details::PODptr<size_type> next = iter;
107
108 // Start 'freed_iter' at beginning of free list
109 void * freed_iter = this->first;
110
111 const size_type partition_size = this->alloc_size();
112
113 do
114 {
115 // increment next
116 next = next.next();
117
118 // delete all contained objects that aren't freed
119
120 // Iterate 'i' through all chunks in the memory block
121 for (char * i = iter.begin(); i != iter.end(); i += partition_size)
122 {
123 // If this chunk is free
124 if (i == freed_iter)
125 {
126 // Increment freed_iter to point to next in free list
127 freed_iter = nextof(freed_iter);
128
129 // Continue searching chunks in the memory block
130 continue;
131 }
132
133 // This chunk is not free (allocated), so call its destructor
134 static_cast<T *>(static_cast<void *>(i))->~T();
135 // and continue searching chunks in the memory block
136 }
137
138 // free storage
139 (UserAllocator::free)(iter.begin());
140
141 // increment iter
142 iter = next;
143 } while (iter.valid());
144
145 // Make the block list empty so that the inherited destructor doesn't try to
146 // free it again.
147 this->list.invalidate();
148 }
149
150 } // namespace boost
151
152 // The following code might be put into some Boost.Config header in a later revision
153 #ifdef __BORLANDC__
154 # pragma option pop
155 #endif
156
157 #endif
158