oro_allocator.hpp

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 //#define ORO_USE_SGI_EXT
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             // if present in pool, return pool item
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             // if found, return item :
00065             if ( r.first != r.second ) {
00066                 ret = r.first->second;
00067                 r.first->second = 0; // clear out
00068                 //std::cerr << "Using grown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
00069                 return ret;
00070             }
00071 
00072             // fallback on allocator...
00073             // ret is still zero here
00074             pool.insert( typename pool_type::value_type(n,ret) );     // store free location.
00075             ret = this->_grow(n, hint);
00076             //std::cerr << "Allocated ungrown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
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 //             if ( find( r.first, r.second, typename pool_type::value_type(n,p) ) != r.second )
00085 //                 assert(false && "Do not deallocate twice !");
00086             while ( r.first != r.second && r.first->second != 0  )
00087                 ++r.first;
00088             // if found, store item :
00089             if ( r.first != r.second ) {
00090                 r.first->second = p;
00091                 //std::cerr << "Storing grown: "<< p <<" of size "<<n<<" in "<<typeid(p).name()<<std::endl;
00092                 return;
00093             }
00094             // if not found, we did not allocate it !
00095             //std::cerr << "Deallocating ungrown: "<<p << " of size "<<n<<" in "<<typeid(p).name()<<std::endl;
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 ) );     // store mem location.
00116             //std::cerr << "Added   : "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
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 ); // erase unused slot.
00132                 //std::cerr << "Removed: "<<t << " of size "<<n<<" in "<<typeid(t).name()<<std::endl;
00133                 _shrink(t,n);
00134                 return;
00135             }
00136             //std::cerr << "Unable to remove "<<n<<std::endl;
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         // the pool stores block-size/pointer pairs. Also uses Alloc for allocation.
00163 #ifdef ORO_USE_SGI_EXT
00164         // hash_multimap is non-standard C++. use std::multimap instead...
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         // stores blocks -> memory map for allocated memory.
00172         struct pool_wrapper_type : public pool_type {
00173             ~pool_wrapper_type() {
00174                 // free all memory.
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 //     template< class T, class A>
00189 //     Mutex local_allocator<T,A>::pool_lock;
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     // use the std::malloc_alloc class !
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

Generated on Tue Aug 25 14:17:22 2009 for Orocos Real-Time Toolkit by  doxygen 1.5.8