Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / server / supernova / utilities / static_allocator.hpp
blobb8ac7851c8da83abda643d26841c8dca590ead7c
1 // static 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_STATIC_ALLOCATOR_HPP
20 #define UTILITIES_STATIC_ALLOCATOR_HPP
22 extern "C"
24 #include "tlsf.h"
27 #include <exception>
29 #include <array>
30 #include <boost/noncopyable.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/mpl/arithmetic.hpp>
33 #include <boost/mpl/modulus.hpp>
35 #include "nova-tt/spin_lock.hpp"
36 #include "nova-tt/dummy_mutex.hpp"
38 namespace nova
41 /** constant-sized, pooled memory allocator based on TLSF allocator
43 * \todo this violates the allocator requirement in 20.1.5, paragraph 4
44 * objects have to be freed using the same instance that was used
45 * to allocate them.
47 * */
48 template <class T,
49 std::size_t count,
50 bool blocking = false>
51 class static_allocator
52 #if 1
54 boost::noncopyable
55 #endif
57 static const std::size_t bytes = 2 * count * sizeof(T) + 4096 * 2;
59 BOOST_STATIC_ASSERT((boost::mpl::modulus<boost::mpl::int_<bytes>, boost::mpl::int_<sizeof(long)> >::value == 0));
61 static const std::size_t poolsize = bytes/sizeof(long);
63 typedef typename boost::mpl::if_c<blocking,
64 spin_lock,
65 dummy_mutex>::type mutex_type;
67 typedef typename mutex_type::scoped_lock scoped_lock;
69 struct data:
70 mutex_type
72 #if 0
73 data(void){}
75 data(data const & rhs)
77 pool = rhs.pool;
79 #endif
81 std::array<long, poolsize> pool;
84 public:
85 typedef std::size_t size_type;
86 typedef std::ptrdiff_t difference_type;
87 typedef T* pointer;
88 typedef const T* const_pointer;
89 typedef T& reference;
90 typedef const T& const_reference;
91 typedef T value_type;
93 template <class U> struct rebind
95 typedef static_allocator<U, count, blocking> other;
98 static_allocator(void) throw()
100 data_.pool.assign(0);
101 init_memory_pool(bytes, data_.pool.begin());
104 #if 0
105 template <class U, std::size_t bytes_, bool b>
106 static_allocator(static_allocator<U, bytes_, b> const & rhs) throw()
108 data_.pool.assign(0);
109 init_memory_pool(bytes, data_.pool.begin());
111 #endif
113 ~static_allocator() throw()
115 destroy_memory_pool(data_.pool.begin());
118 pointer address(reference x) const
120 return &x;
123 const_pointer address(const_reference x) const
125 return &x;
128 pointer allocate(size_type n,
129 const_pointer hint = 0)
131 scoped_lock lock(data_);
132 pointer ret = static_cast<pointer>(malloc_ex(n * sizeof(T), data_.pool.begin()));
134 if (ret == 0)
135 throw std::bad_alloc();
137 return ret;
140 void deallocate(pointer p, size_type n)
142 scoped_lock lock(data_);
143 free_ex(p, data_.pool.begin());
146 size_type max_size() const throw()
148 return count;
151 void construct(pointer p, const T& val)
153 ::new(p) T(val);
156 void destroy(pointer p)
158 p->~T();
161 private:
162 data data_;
166 template<typename T, std::size_t ts, bool tb, typename U, std::size_t us, bool ub>
167 bool operator==( static_allocator<T, ts, tb> const& left, static_allocator<U, us, ub> const& right )
169 return !(left != right);
172 template<typename T, std::size_t ts, bool tb, typename U, std::size_t us, bool ub>
173 bool operator!=( static_allocator<T, ts, tb> const& left, static_allocator<U, us, ub> const& right )
175 return true;
179 } /* namespace nova */
181 #endif /* UTILITIES_STATIC_ALLOCATOR_HPP */