SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / server / supernova / utilities / static_pooled_class.hpp
blobfc240e22843d68ee3e85e09a38c4f13a70f449d6
1 // static pooled class
2 // Copyright (C) 2009 Tim Blechmann
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef UTILITIES_STATIC_POOLED_CLASS_HPP
20 #define UTILITIES_STATIC_POOLED_CLASS_HPP
22 #include <cstddef>
24 #include <boost/mpl/equal_to.hpp>
25 #include <boost/mpl/if.hpp>
27 #include "freelist.hpp"
28 #include "static_pool.hpp"
30 namespace nova
33 /**
34 * base class for a class, which uses a static memory pool for
35 * memory allocation.
37 * memory is allocated from a static pool and freed to a lock-free
38 * freelist, which is freed during the memory allocation routine.
39 * this way, the derived class can be allocated and freed from
40 * different threads, while all the access to the pool is done from
41 * the allocating thread.
43 * \tparam pool_locking specifies the locking policy for the object
44 * pool (default: nonblocking)
46 * \tparam recover_count limits the number of objects to be disposed
47 * from the freelist to avoid (default: dispose all objects
48 * of freelist)
50 * \todo we could allocate one word more and store the size of the
51 * chunk just before the object. if a disposed object is large
52 * enough for a request, it wouldn't need to be added to the
53 * memory pool.
55 * */
56 template <typename tag,
57 std::size_t pool_size,
58 bool pool_locking = false,
59 unsigned int recover_count = 0 >
60 class static_pooled_class
62 protected:
63 static_pooled_class(void)
66 static_pooled_class(static_pooled_class const & rhs)
69 ~static_pooled_class(void)
72 private:
73 /** free one object from freelist
75 * \return true if freelist is empty
77 * */
78 static inline bool free_disposed_object(void)
80 void * chunk = disposed_objects.pop();
81 if (chunk == NULL)
82 return true;
83 object_pool.free(chunk);
84 return false;
87 struct disposing_allocator
89 static void * allocate(std::size_t size)
91 free_disposed_objects();
92 return object_pool.malloc(size);
96 struct dispose_n_object_allocator
98 static void * allocate(std::size_t size)
100 for (unsigned int i = 0; i != recover_count; ++i) {
101 bool freelist_empty = free_disposed_object();
102 if (freelist_empty)
103 break;
106 for (;;)
108 void * ret = object_pool.malloc(size);
110 if (ret)
111 return ret;
112 if (free_disposed_object())
113 return NULL; /* no object in freelist, we */
118 typedef typename boost::mpl::equal_to<boost::mpl::int_<recover_count>,
119 boost::mpl::int_<0>
120 > greater_zero;
121 typedef typename boost::mpl::if_<greater_zero,
122 dispose_n_object_allocator,
123 disposing_allocator
124 >::type allocator;
126 public:
127 static inline void * allocate(std::size_t size)
129 #ifndef NOVA_MEMORY_DEBUGGING
130 size = std::max(2*sizeof(void*), size); /* size requirement for lockfree freelist */
131 return allocator::allocate(size);
132 #else
133 return malloc(size);
134 #endif
137 inline void* operator new(std::size_t size)
139 return allocate(size);
142 static inline void free_disposed_objects(void)
144 for(;;) {
145 if (free_disposed_object())
146 return;
150 static inline void deallocate(void * p)
152 #ifndef NOVA_MEMORY_DEBUGGING
153 disposed_objects.push(p);
154 #else
155 free(p);
156 #endif
159 inline void operator delete(void * p)
161 deallocate(p);
164 typedef static_pool<pool_size, pool_locking> object_pool_type;
166 static object_pool_type object_pool;
167 static freelist disposed_objects;
170 template <typename tag,
171 std::size_t pool_size,
172 bool pool_locking,
173 unsigned int recover_count>
174 typename static_pooled_class<tag, pool_size, pool_locking, recover_count>::object_pool_type
175 static_pooled_class<tag, pool_size, pool_locking, recover_count>::object_pool(true);
177 template <typename tag,
178 std::size_t pool_size,
179 bool pool_locking,
180 unsigned int recover_count>
181 freelist static_pooled_class<tag, pool_size, pool_locking, recover_count>::disposed_objects;
184 } /* namespace nova */
186 #endif /* UTILITIES_STATIC_POOLED_CLASS_HPP */