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