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