Orocos Real-Time Toolkit  2.9.0
oro_allocator.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Thu Oct 22 11:59:07 CEST 2009 oro_allocator.hpp
3 
4  oro_allocator.hpp - description
5  -------------------
6  begin : Thu October 22 2009
7  copyright : (C) 2009 Peter Soetens
8  email : peter@thesourcworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #ifndef ORO_ALOCATOR_HPP
40 #define ORO_ALOCATOR_HPP
41 
42 #include <memory>
43 #include <utility>
44 #include <map>
45 
46 #include "MutexLock.hpp"
47 #include "oro_malloc.h"
48 
49 namespace RTT { namespace os {
63  template <class T, class Alloc = std::allocator<T> >
65  {
66  public:
67  typedef typename Alloc::value_type value_type;
68  typedef typename Alloc::pointer pointer;
69  typedef typename Alloc::const_pointer const_pointer;
70  typedef typename Alloc::reference reference;
71  typedef typename Alloc::const_reference const_reference;
72  typedef typename Alloc::size_type size_type;
73  typedef typename Alloc::difference_type difference_type;
74  //...
75  public:
76  pointer address(reference x) const {
77  return Alloc().address(x);
78  }
79 
80  const_pointer address(const_reference x) const {
81  return Alloc().address(x);
82  }
83  public:
84  pointer allocate(size_type n, const_pointer hint = 0) {
85  pointer ret = 0;
86  if (n == 0)
87  return ret;
88  MutexLock lock( pool_lock );
89  // if present in pool, return pool item
90  std::pair<pool_it,pool_it> r = pool.equal_range( n );
91  while ( r.first != r.second && r.first->second == 0 )
92  ++r.first;
93  // if found, return item :
94  if ( r.first != r.second ) {
95  ret = r.first->second;
96  r.first->second = 0; // clear out
97  //std::cerr << "Using grown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
98  return ret;
99  }
100 
101  // fallback on allocator...
102  // ret is still zero here
103  pool.insert( typename pool_type::value_type(n,ret) ); // store free location.
104  ret = this->_grow(n, hint);
105  //std::cerr << "Allocated ungrown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
106 
107  return ret;
108  }
109 
110  void deallocate(pointer p, size_type n) {
111  MutexLock lock( pool_lock );
112  std::pair<pool_it,pool_it> r = pool.equal_range( n );
113 // if ( find( r.first, r.second, typename pool_type::value_type(n,p) ) != r.second )
114 // assert(false && "Do not deallocate twice !");
115  while ( r.first != r.second && r.first->second != 0 )
116  ++r.first;
117  // if found, store item :
118  if ( r.first != r.second ) {
119  r.first->second = p;
120  //std::cerr << "Storing grown: "<< p <<" of size "<<n<<" in "<<typeid(p).name()<<std::endl;
121  return;
122  }
123  // if not found, we did not allocate it !
124  //std::cerr << "Deallocating ungrown: "<<p << " of size "<<n<<" in "<<typeid(p).name()<<std::endl;
125  this->_shrink(p,n);
126  }
127 
128  size_type max_size() const {
129  return Alloc().max_size();
130  }
131 
132  void construct(pointer p, const value_type& x) {
133  Alloc().construct(p, x);
134  }
135 
136  void destroy(pointer p) { Alloc().destroy(p); }
137 
141  void grow(size_type n, const_pointer hint = 0) {
142  MutexLock lock( pool_lock );
143  pointer ret = this->_grow(n, hint);
144  pool.insert( typename pool_type::value_type( n,ret ) ); // store mem location.
145  //std::cerr << "Added : "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
146  }
147 
151  void shrink(size_type n) {
152  if (n == 0)
153  return;
154  MutexLock lock( pool_lock );
155  std::pair<pool_it,pool_it> r = pool.equal_range( n );
156  while ( r.first != r.second && r.first->second == 0 )
157  ++r.first;
158  if ( r.first != r.second ) {
159  pointer t = r.first->second;
160  pool.erase( r.first ); // erase unused slot.
161  //std::cerr << "Removed: "<<t << " of size "<<n<<" in "<<typeid(t).name()<<std::endl;
162  _shrink(t,n);
163  return;
164  }
165  //std::cerr << "Unable to remove "<<n<<std::endl;
166  }
167  public:
169  local_allocator(const local_allocator&) { /* Use default mutex and empty pool */ }
171  template <class U, class A>
172  local_allocator(const local_allocator<U,A>&) { /* Use default mutex and empty pool */ }
173 
174  template <class U>
176 
177  void operator=(const local_allocator&) { /* Keep existing mutex and pool. */ }
178 
179  private:
180  Mutex pool_lock;
184  pointer _grow(size_type n, const_pointer hint = 0) {
185  return Alloc().allocate( n, hint );
186  }
187 
188  void _shrink( pointer t, size_type n) {
189  Alloc().deallocate( t, n);
190  }
191 
192  // the pool stores block-size/pointer pairs. Also uses Alloc for allocation.
193  typedef std::multimap< size_t, pointer> pool_type;
194  typedef typename pool_type::iterator pool_it;
195  typedef typename pool_type::const_iterator pool_cit;
196  // stores blocks -> memory map for allocated memory.
197  struct pool_wrapper_type : public pool_type {
198  ~pool_wrapper_type() {
199  // free all memory.
200  typename pool_type::iterator it = this->begin();
201  for (; it != this->end(); ++it ) {
202  Alloc().deallocate(it->second, it->first );
203  }
204  }
205  };
206  pool_wrapper_type pool;
207 
208  };
209 
210  template <class T, class A, class A2>
211  inline bool operator==(const local_allocator<T,A>& ,
212  const local_allocator<T,A2>& ) {
213  return false;
214  }
215 
216  template <class T, class A, class A2>
217  inline bool operator!=(const local_allocator<T,A>& ,
218  const local_allocator<T,A2>& ) {
219  return true;
220  }
221 
222  template <class T, class A>
223  inline bool operator==(const local_allocator<T,A>& ,
224  const local_allocator<T,A>& ) {
225  return true;;
226  }
227 
228  template <class T, class A>
229  inline bool operator!=(const local_allocator<T,A>&,
230  const local_allocator<T,A>&) {
231  return false;
232  }
233 
234  template<>
235  class local_allocator<void>
236  {
237  public:
238  typedef void value_type;
239  typedef void* pointer;
240  typedef const void* const_pointer;
241 
242  template <class U>
243  struct rebind { typedef local_allocator<U> other; };
244  };
245 
251  template <class T> class rt_allocator
252  {
253  public:
254  typedef T value_type;
255  typedef value_type* pointer;
256  typedef const value_type* const_pointer;
257  typedef value_type& reference;
258  typedef const value_type& const_reference;
259  typedef std::size_t size_type;
260  typedef std::ptrdiff_t difference_type;
261  //...
262  public:
263  pointer address(reference x) const {
264  return &x;
265  }
266 
267  const_pointer address(const_reference x) const {
268  return &x;
269  }
270  public:
271  pointer allocate(size_type n, const_pointer = 0) {
272  void* p = oro_rt_malloc(n * sizeof(T));
273  if (!p)
274  throw std::bad_alloc();
275  return static_cast<pointer>(p);
276  }
277 
278  void deallocate(pointer p, size_type) {
279  oro_rt_free(p);
280  }
281 
282  size_type max_size() const {
283  return static_cast<size_type>(-1) / sizeof(value_type);
284  }
285 
286  void construct(pointer p, const value_type& x) {
287  new(p) value_type(x);
288  }
289 
290  void destroy(pointer p) { p->~value_type(); }
291 
292  public:
296  template <class U>
298  void operator=(const rt_allocator&) {}
299 
300  template <class U>
301  struct rebind { typedef rt_allocator<U> other; };
302  private:
303  };
304 
305  template <class T>
306  inline bool operator==(const rt_allocator<T>&,
307  const rt_allocator<T>&) {
308  return true;
309  }
310 
311  template <class T>
312  inline bool operator!=(const rt_allocator<T>&,
313  const rt_allocator<T>&) {
314  return false;
315  }
316 
317  template<> class rt_allocator<void>
318  {
319  public:
320  typedef void value_type;
321  typedef void* pointer;
322  typedef const void* const_pointer;
323 
324  template <class U>
325  struct rebind { typedef rt_allocator<U> other; };
326  };
327 }}
328 
329 #endif
Alloc::const_pointer const_pointer
A simple local allocator which keeps a small pool which you can grow manually with grow()...
pointer allocate(size_type n, const_pointer=0)
void construct(pointer p, const value_type &x)
void grow(size_type n, const_pointer hint=0)
Grow local pool with room for at least n additional items.
rt_allocator(const rt_allocator &)
const_pointer address(const_reference x) const
size_type max_size() const
void operator=(const rt_allocator &)
void deallocate(pointer p, size_type)
A real-time malloc allocator which allocates every block with oro_rt_malloc() and deallocates with or...
void deallocate(pointer p, size_type n)
local_allocator(const local_allocator &)
pointer allocate(size_type n, const_pointer hint=0)
const_pointer address(const_reference x) const
local_allocator< U, typename Alloc::template rebind< U >::other > other
size_type max_size() const
void shrink(size_type n)
Shrink local pool with n items.
void destroy(pointer p)
void construct(pointer p, const value_type &x)
Alloc::value_type value_type
#define oro_rt_malloc
Definition: oro_malloc.h:54
Wraps the oro_rt_ allocator functions to standard C malloc function family or TLSF if available...
local_allocator(const local_allocator< U, A > &)
Alloc::size_type size_type
const value_type & const_reference
Alloc::reference reference
rt_allocator(const rt_allocator< U > &)
std::ptrdiff_t difference_type
pointer address(reference x) const
bool operator==(const local_allocator< T, A > &, const local_allocator< T, A2 > &)
void operator=(const local_allocator &)
Alloc::difference_type difference_type
pointer address(reference x) const
An object oriented wrapper around a non recursive mutex.
Definition: Mutex.hpp:92
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
const value_type * const_pointer
Alloc::const_reference const_reference
bool operator!=(const local_allocator< T, A > &, const local_allocator< T, A2 > &)
#define oro_rt_free
Definition: oro_malloc.h:55
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...
Definition: MutexLock.hpp:51