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.
13 //
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.
18
19 #pragma once
20
21 extern "C" {
22 #include "tlsf.h"
23 }
24
25 #include <exception>
26
27 #include <array>
28
29 #include "nova-tt/spin_lock.hpp"
30 #include "nova-tt/dummy_mutex.hpp"
31
32 namespace nova {
33
34 /** constant-sized, pooled memory allocator based on TLSF allocator
35 *
36 * \todo this violates the allocator requirement in 20.1.5, paragraph 4
37 * objects have to be freed using the same instance that was used
38 * to allocate them.
39 *
40 * */
41 template <class T, std::size_t count, bool blocking = false> class static_allocator {
42 static const std::size_t bytes = 2 * count * sizeof(T) + 4096 * 2;
43
44 static_assert(bytes % sizeof(long) == 0, "static_allocator: bytes not an integer mutiple of sizeof(long)");
45
46 static const std::size_t poolsize = bytes / sizeof(long);
47
48 typedef typename boost::mpl::if_c<blocking, spin_lock, dummy_mutex>::type mutex_type;
49
50 typedef typename mutex_type::scoped_lock scoped_lock;
51
52 struct data : mutex_type {
53 #if 0
54 data(void){}
55
56 data(data const & rhs)
57 {
58 pool = rhs.pool;
59 }
60 #endif
61
62 std::array<long, poolsize> pool;
63 };
64
65 public:
66 typedef std::size_t size_type;
67 typedef std::ptrdiff_t difference_type;
68 typedef T* pointer;
69 typedef const T* const_pointer;
70 typedef T& reference;
71 typedef const T& const_reference;
72 typedef T value_type;
73
74 template <class U> struct rebind { typedef static_allocator<U, count, blocking> other; };
75
static_allocator(void)76 static_allocator(void) throw() {
77 data_.pool.assign(0);
78 init_memory_pool(bytes, data_.pool.begin());
79 }
80
81 static_allocator(static_allocator const&) = delete;
82
83 #if 0
84 template <class U, std::size_t bytes_, bool b>
85 static_allocator(static_allocator<U, bytes_, b> const & rhs) throw()
86 {
87 data_.pool.assign(0);
88 init_memory_pool(bytes, data_.pool.begin());
89 }
90 #endif
91
~static_allocator()92 ~static_allocator() throw() { destroy_memory_pool(data_.pool.begin()); }
93
address(reference x) const94 pointer address(reference x) const { return &x; }
95
address(const_reference x) const96 const_pointer address(const_reference x) const { return &x; }
97
allocate(size_type n,const_pointer hint=0)98 pointer allocate(size_type n, const_pointer hint = 0) {
99 scoped_lock lock(data_);
100 pointer ret = static_cast<pointer>(malloc_ex(n * sizeof(T), data_.pool.begin()));
101
102 if (ret == 0)
103 throw std::bad_alloc();
104
105 return ret;
106 }
107
deallocate(pointer p,size_type n)108 void deallocate(pointer p, size_type n) {
109 scoped_lock lock(data_);
110 free_ex(p, data_.pool.begin());
111 }
112
max_size() const113 size_type max_size() const throw() { return count; }
114
construct(pointer p,const T & val)115 void construct(pointer p, const T& val) { ::new (p) T(val); }
116
destroy(pointer p)117 void destroy(pointer p) { p->~T(); }
118
119 private:
120 data data_;
121 };
122
123
124 template <typename T, std::size_t ts, bool tb, typename U, std::size_t us, bool ub>
operator ==(static_allocator<T,ts,tb> const & left,static_allocator<U,us,ub> const & right)125 bool operator==(static_allocator<T, ts, tb> const& left, static_allocator<U, us, ub> const& right) {
126 return !(left != right);
127 }
128
129 template <typename T, std::size_t ts, bool tb, typename U, std::size_t us, bool ub>
operator !=(static_allocator<T,ts,tb> const & left,static_allocator<U,us,ub> const & right)130 bool operator!=(static_allocator<T, ts, tb> const& left, static_allocator<U, us, ub> const& right) {
131 return true;
132 }
133
134
135 } /* namespace nova */
136