00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef ORO_ALOCATOR_HPP
00040 #define ORO_ALOCATOR_HPP
00041
00042 #include <memory>
00043 #include <utility>
00044 #include <map>
00045
00046 #include "MutexLock.hpp"
00047 #include "oro_malloc.h"
00048
00049 namespace RTT { namespace os {
00063 template <class T, class Alloc = std::allocator<T> >
00064 class local_allocator
00065 {
00066 public:
00067 typedef typename Alloc::value_type value_type;
00068 typedef typename Alloc::pointer pointer;
00069 typedef typename Alloc::const_pointer const_pointer;
00070 typedef typename Alloc::reference reference;
00071 typedef typename Alloc::const_reference const_reference;
00072 typedef typename Alloc::size_type size_type;
00073 typedef typename Alloc::difference_type difference_type;
00074
00075 public:
00076 pointer address(reference x) const {
00077 return Alloc().address(x);
00078 }
00079
00080 const_pointer address(const_reference x) const {
00081 return Alloc().address(x);
00082 }
00083 public:
00084 pointer allocate(size_type n, const_pointer hint = 0) {
00085 pointer ret = 0;
00086 if (n == 0)
00087 return ret;
00088 MutexLock lock( pool_lock );
00089
00090 std::pair<pool_it,pool_it> r = pool.equal_range( n );
00091 while ( r.first != r.second && r.first->second == 0 )
00092 ++r.first;
00093
00094 if ( r.first != r.second ) {
00095 ret = r.first->second;
00096 r.first->second = 0;
00097
00098 return ret;
00099 }
00100
00101
00102
00103 pool.insert( typename pool_type::value_type(n,ret) );
00104 ret = this->_grow(n, hint);
00105
00106
00107 return ret;
00108 }
00109
00110 void deallocate(pointer p, size_type n) {
00111 MutexLock lock( pool_lock );
00112 std::pair<pool_it,pool_it> r = pool.equal_range( n );
00113
00114
00115 while ( r.first != r.second && r.first->second != 0 )
00116 ++r.first;
00117
00118 if ( r.first != r.second ) {
00119 r.first->second = p;
00120
00121 return;
00122 }
00123
00124
00125 this->_shrink(p,n);
00126 }
00127
00128 size_type max_size() const {
00129 return Alloc().max_size();
00130 }
00131
00132 void construct(pointer p, const value_type& x) {
00133 Alloc().construct(p, x);
00134 }
00135
00136 void destroy(pointer p) { Alloc().destroy(p); }
00137
00141 void grow(size_type n, const_pointer hint = 0) {
00142 MutexLock lock( pool_lock );
00143 pointer ret = this->_grow(n, hint);
00144 pool.insert( typename pool_type::value_type( n,ret ) );
00145
00146 }
00147
00151 void shrink(size_type n) {
00152 if (n == 0)
00153 return;
00154 MutexLock lock( pool_lock );
00155 std::pair<pool_it,pool_it> r = pool.equal_range( n );
00156 while ( r.first != r.second && r.first->second == 0 )
00157 ++r.first;
00158 if ( r.first != r.second ) {
00159 pointer t = r.first->second;
00160 pool.erase( r.first );
00161
00162 _shrink(t,n);
00163 return;
00164 }
00165
00166 }
00167 public:
00168 local_allocator() {}
00169 local_allocator(const local_allocator&) {}
00170 ~local_allocator() {}
00171 template <class U, class A>
00172 local_allocator(const local_allocator<U,A>&) {}
00173
00174 template <class U>
00175 struct rebind { typedef local_allocator<U, typename Alloc::template rebind<U>::other > other; };
00176 private:
00177 Mutex pool_lock;
00181 pointer _grow(size_type n, const_pointer hint = 0) {
00182 return Alloc().allocate( n, hint );
00183 }
00184
00185 void _shrink( pointer t, size_type n) {
00186 Alloc().deallocate( t, n);
00187 }
00188
00189 void operator=(const local_allocator&);
00190
00191
00192 typedef std::multimap< size_t, pointer> pool_type;
00193 typedef typename pool_type::iterator pool_it;
00194 typedef typename pool_type::const_iterator pool_cit;
00195
00196 struct pool_wrapper_type : public pool_type {
00197 ~pool_wrapper_type() {
00198
00199 typename pool_type::iterator it = this->begin();
00200 for (; it != this->end(); ++it ) {
00201 Alloc().deallocate(it->second, it->first );
00202 }
00203 }
00204 };
00205 static pool_wrapper_type pool;
00206
00207 };
00208
00209 template< class T, class A>
00210 typename local_allocator<T,A>::pool_wrapper_type local_allocator<T,A>::pool;
00211
00212
00213
00214
00215 template <class T, class A, class A2>
00216 inline bool operator==(const local_allocator<T,A>& ,
00217 const local_allocator<T,A2>& ) {
00218 return false;
00219 }
00220
00221 template <class T, class A, class A2>
00222 inline bool operator!=(const local_allocator<T,A>& ,
00223 const local_allocator<T,A2>& ) {
00224 return true;
00225 }
00226
00227 template <class T, class A>
00228 inline bool operator==(const local_allocator<T,A>& ,
00229 const local_allocator<T,A>& ) {
00230 return true;;
00231 }
00232
00233 template <class T, class A>
00234 inline bool operator!=(const local_allocator<T,A>&,
00235 const local_allocator<T,A>&) {
00236 return false;
00237 }
00238
00239 template<>
00240 class local_allocator<void>
00241 {
00242 public:
00243 typedef void value_type;
00244 typedef void* pointer;
00245 typedef const void* const_pointer;
00246
00247 template <class U>
00248 struct rebind { typedef local_allocator<U> other; };
00249 };
00250
00256 template <class T> class rt_allocator
00257 {
00258 public:
00259 typedef T value_type;
00260 typedef value_type* pointer;
00261 typedef const value_type* const_pointer;
00262 typedef value_type& reference;
00263 typedef const value_type& const_reference;
00264 typedef std::size_t size_type;
00265 typedef std::ptrdiff_t difference_type;
00266
00267 public:
00268 pointer address(reference x) const {
00269 return &x;
00270 }
00271
00272 const_pointer address(const_reference x) const {
00273 return &x;
00274 }
00275 public:
00276 pointer allocate(size_type n, const_pointer = 0) {
00277 void* p = oro_rt_malloc(n * sizeof(T));
00278 if (!p)
00279 throw std::bad_alloc();
00280 return static_cast<pointer>(p);
00281 }
00282
00283 void deallocate(pointer p, size_type) {
00284 oro_rt_free(p);
00285 }
00286
00287 size_type max_size() const {
00288 return static_cast<size_type>(-1) / sizeof(value_type);
00289 }
00290
00291 void construct(pointer p, const value_type& x) {
00292 new(p) value_type(x);
00293 }
00294
00295 void destroy(pointer p) { p->~value_type(); }
00296
00297 public:
00298 rt_allocator() {}
00299 rt_allocator(const rt_allocator&) {}
00300 ~rt_allocator() {}
00301 template <class U>
00302 rt_allocator(const rt_allocator<U>&) {}
00303
00304 template <class U>
00305 struct rebind { typedef rt_allocator<U> other; };
00306 private:
00307 void operator=(const rt_allocator&);
00308 };
00309
00310 template <class T>
00311 inline bool operator==(const rt_allocator<T>&,
00312 const rt_allocator<T>&) {
00313 return true;
00314 }
00315
00316 template <class T>
00317 inline bool operator!=(const rt_allocator<T>&,
00318 const rt_allocator<T>&) {
00319 return false;
00320 }
00321
00322 template<> class rt_allocator<void>
00323 {
00324 public:
00325 typedef void value_type;
00326 typedef void* pointer;
00327 typedef const void* const_pointer;
00328
00329 template <class U>
00330 struct rebind { typedef rt_allocator<U> other; };
00331 };
00332 }}
00333
00334 #endif