bumping version to 3.5-rc1
[supercollider.git] / server / supernova / utilities / tl_allocator.hpp
blob2f0cea3326a2540d40f5c4b09056fdde5a752fb1
1 // thread-local real-time safe allocator class
2 // Copyright (C) 2008 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_TL_ALLOCATOR_HPP
20 #define UTILITIES_TL_ALLOCATOR_HPP
22 extern "C"
24 #include "tlsf.h"
27 #include <exception>
28 #include <cstring>
30 #include <boost/array.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/mpl/modulus.hpp>
33 #include <boost/mpl/arithmetic.hpp>
34 #include <boost/thread/tss.hpp>
36 #include "branch_hints.hpp"
38 namespace nova
41 namespace detail
44 #ifdef __GNUC__
45 template <std::size_t bytes>
46 class tl_allocator
48 BOOST_STATIC_ASSERT((boost::mpl::modulus<boost::mpl::int_<bytes>, boost::mpl::int_<sizeof(long)> >::value == 0));
50 public:
52 static const std::size_t poolsize = bytes/sizeof(long);
53 typedef std::size_t size_type;
54 typedef std::ptrdiff_t difference_type;
56 tl_allocator(void) throw()
58 if (likely(initialized))
59 return;
61 memset(pool, bytes, 0);
62 init_memory_pool(bytes, pool);
65 void * allocate(size_type n)
67 void * ret = malloc_ex(n, pool);
69 if (ret == 0)
70 throw std::bad_alloc();
72 return ret;
75 void deallocate(void * p)
77 free_ex(p, pool);
80 size_type max_size() const throw()
82 return bytes;
85 static __thread long pool[poolsize];
86 static __thread bool initialized;
89 template <std::size_t bytes>
90 long __thread tl_allocator<bytes>::pool[];
92 template <std::size_t bytes>
93 bool __thread tl_allocator<bytes>::initialized = false;
95 #else
97 template <std::size_t bytes>
98 class tl_allocator
100 BOOST_STATIC_ASSERT((boost::mpl::modulus<boost::mpl::int_<bytes>, boost::mpl::int_<sizeof(long)> >::value == 0));
101 static const std::size_t poolsize = bytes/sizeof(long);
103 struct pool_t
106 pool_t(void)
108 pool.assign(0);
109 init_memory_pool(bytes, pool.begin());
112 ~pool_t(void)
114 destroy_memory_pool(pool.begin());
117 boost::array<long, poolsize> pool;
120 public:
121 typedef std::size_t size_type;
122 typedef std::ptrdiff_t difference_type;
124 tl_allocator(void) throw()
126 if (likely(pool.get()))
127 return;
128 pool.reset(new pool_t());
131 tl_allocator(tl_allocator const & rhs) throw()
134 void * allocate(size_type n)
136 void * ret = malloc_ex(n, pool->pool.begin());
138 if (ret == 0)
139 throw std::bad_alloc();
141 return ret;
144 void deallocate(void * p)
146 free_ex(p, pool->pool.begin());
149 size_type max_size() const throw()
151 return bytes;
154 typedef boost::thread_specific_ptr<pool_t> pool_ptr;
155 static pool_ptr pool;
158 template <std::size_t bytes>
159 typename tl_allocator<bytes>::pool_ptr tl_allocator<bytes>::pool;
161 #endif
167 * realtime allocator:
168 * allocates from a thread-local memory pool via the malloc implementation of tlsf
170 * it is not completely stl compliant
171 * memory allocated from one instance can be deallocated from each other instance
172 * of this class as long as it is done from the same thread
174 * */
175 template <typename T, std::size_t bytes = 8 * 1024 * 1024>
176 class tl_allocator
178 public:
179 typedef std::size_t size_type;
180 typedef std::ptrdiff_t difference_type;
181 typedef T* pointer;
182 typedef const T* const_pointer;
183 typedef T& reference;
184 typedef const T& const_reference;
185 typedef T value_type;
187 template <class U> struct rebind
189 typedef tl_allocator<U, bytes> other;
192 tl_allocator(void) throw()
195 template <class U, std::size_t bytes_>
196 tl_allocator(tl_allocator<U, bytes_> const & rhs) throw()
199 pointer address(reference x) const
201 return &x;
204 const_pointer address(const_reference x) const
206 return &x;
209 pointer allocate(size_type n,
210 const_pointer hint = 0)
212 return static_cast<pointer> (allocator.allocate(n * sizeof(T)));
215 void deallocate(pointer p, size_type n)
217 allocator.deallocate(p);
220 size_type max_size() const throw()
222 return bytes;
225 void construct(pointer p, const T& val)
227 ::new(p) T(val);
230 void destroy(pointer p)
232 p->~T();
235 private:
236 detail::tl_allocator<bytes> allocator;
239 } /* namespace nova */
241 #endif /* UTILITIES_TL_ALLOCATOR_HPP */