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 typedef void value_type;
00243 typedef void* pointer;
00244 typedef const void* const_pointer;
00245
00246 template <class U>
00247 struct rebind { typedef local_allocator<U> other; };
00248 };
00249
00255 template <class T> class rt_allocator
00256 {
00257 public:
00258 typedef T value_type;
00259 typedef value_type* pointer;
00260 typedef const value_type* const_pointer;
00261 typedef value_type& reference;
00262 typedef const value_type& const_reference;
00263 typedef std::size_t size_type;
00264 typedef std::ptrdiff_t difference_type;
00265
00266 public:
00267 pointer address(reference x) const {
00268 return &x;
00269 }
00270
00271 const_pointer address(const_reference x) const {
00272 return &x;
00273 }
00274 public:
00275 pointer allocate(size_type n, const_pointer = 0) {
00276 void* p = oro_rt_malloc(n * sizeof(T));
00277 if (!p)
00278 throw std::bad_alloc();
00279 return static_cast<pointer>(p);
00280 }
00281
00282 void deallocate(pointer p, size_type) {
00283 oro_rt_free(p);
00284 }
00285
00286 size_type max_size() const {
00287 return static_cast<size_type>(-1) / sizeof(value_type);
00288 }
00289
00290 void construct(pointer p, const value_type& x) {
00291 new(p) value_type(x);
00292 }
00293
00294 void destroy(pointer p) { p->~value_type(); }
00295
00296 public:
00297 rt_allocator() {}
00298 rt_allocator(const rt_allocator&) {}
00299 ~rt_allocator() {}
00300 template <class U>
00301 rt_allocator(const rt_allocator<U>&) {}
00302
00303 template <class U>
00304 struct rebind { typedef rt_allocator<U> other; };
00305 private:
00306 void operator=(const rt_allocator&);
00307 };
00308
00309 template <class T>
00310 inline bool operator==(const rt_allocator<T>&,
00311 const rt_allocator<T>&) {
00312 return true;
00313 }
00314
00315 template <class T>
00316 inline bool operator!=(const rt_allocator<T>&,
00317 const rt_allocator<T>&) {
00318 return false;
00319 }
00320
00321 template<> class rt_allocator<void>
00322 {
00323 typedef void value_type;
00324 typedef void* pointer;
00325 typedef const void* const_pointer;
00326
00327 template <class U>
00328 struct rebind { typedef rt_allocator<U> other; };
00329 };
00330 }}
00331
00332 #endif