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
00177 void operator=(const local_allocator&) { }
00178
00179 private:
00180 Mutex pool_lock;
00184 pointer _grow(size_type n, const_pointer hint = 0) {
00185 return Alloc().allocate( n, hint );
00186 }
00187
00188 void _shrink( pointer t, size_type n) {
00189 Alloc().deallocate( t, n);
00190 }
00191
00192
00193 typedef std::multimap< size_t, pointer> pool_type;
00194 typedef typename pool_type::iterator pool_it;
00195 typedef typename pool_type::const_iterator pool_cit;
00196
00197 struct pool_wrapper_type : public pool_type {
00198 ~pool_wrapper_type() {
00199
00200 typename pool_type::iterator it = this->begin();
00201 for (; it != this->end(); ++it ) {
00202 Alloc().deallocate(it->second, it->first );
00203 }
00204 }
00205 };
00206 pool_wrapper_type pool;
00207
00208 };
00209
00210 template <class T, class A, class A2>
00211 inline bool operator==(const local_allocator<T,A>& ,
00212 const local_allocator<T,A2>& ) {
00213 return false;
00214 }
00215
00216 template <class T, class A, class A2>
00217 inline bool operator!=(const local_allocator<T,A>& ,
00218 const local_allocator<T,A2>& ) {
00219 return true;
00220 }
00221
00222 template <class T, class A>
00223 inline bool operator==(const local_allocator<T,A>& ,
00224 const local_allocator<T,A>& ) {
00225 return true;;
00226 }
00227
00228 template <class T, class A>
00229 inline bool operator!=(const local_allocator<T,A>&,
00230 const local_allocator<T,A>&) {
00231 return false;
00232 }
00233
00234 template<>
00235 class local_allocator<void>
00236 {
00237 public:
00238 typedef void value_type;
00239 typedef void* pointer;
00240 typedef const void* const_pointer;
00241
00242 template <class U>
00243 struct rebind { typedef local_allocator<U> other; };
00244 };
00245
00251 template <class T> class rt_allocator
00252 {
00253 public:
00254 typedef T value_type;
00255 typedef value_type* pointer;
00256 typedef const value_type* const_pointer;
00257 typedef value_type& reference;
00258 typedef const value_type& const_reference;
00259 typedef std::size_t size_type;
00260 typedef std::ptrdiff_t difference_type;
00261
00262 public:
00263 pointer address(reference x) const {
00264 return &x;
00265 }
00266
00267 const_pointer address(const_reference x) const {
00268 return &x;
00269 }
00270 public:
00271 pointer allocate(size_type n, const_pointer = 0) {
00272 void* p = oro_rt_malloc(n * sizeof(T));
00273 if (!p)
00274 throw std::bad_alloc();
00275 return static_cast<pointer>(p);
00276 }
00277
00278 void deallocate(pointer p, size_type) {
00279 oro_rt_free(p);
00280 }
00281
00282 size_type max_size() const {
00283 return static_cast<size_type>(-1) / sizeof(value_type);
00284 }
00285
00286 void construct(pointer p, const value_type& x) {
00287 new(p) value_type(x);
00288 }
00289
00290 void destroy(pointer p) { p->~value_type(); }
00291
00292 public:
00293 rt_allocator() {}
00294 rt_allocator(const rt_allocator&) {}
00295 ~rt_allocator() {}
00296 template <class U>
00297 rt_allocator(const rt_allocator<U>&) {}
00298 void operator=(const rt_allocator&) {}
00299
00300 template <class U>
00301 struct rebind { typedef rt_allocator<U> other; };
00302 private:
00303 };
00304
00305 template <class T>
00306 inline bool operator==(const rt_allocator<T>&,
00307 const rt_allocator<T>&) {
00308 return true;
00309 }
00310
00311 template <class T>
00312 inline bool operator!=(const rt_allocator<T>&,
00313 const rt_allocator<T>&) {
00314 return false;
00315 }
00316
00317 template<> class rt_allocator<void>
00318 {
00319 public:
00320 typedef void value_type;
00321 typedef void* pointer;
00322 typedef const void* const_pointer;
00323
00324 template <class U>
00325 struct rebind { typedef rt_allocator<U> other; };
00326 };
00327 }}
00328
00329 #endif