oro_allocator.hpp

00001 #ifndef ORO_ALOCATOR_HPP
00002 #define ORO_ALOCATOR_HPP
00003 
00004 #include <memory>
00005 #include <utility>
00006 #include <map>
00007 
00008 #include "MutexLock.hpp"
00009 #include "oro_malloc.h"
00010 
00011 namespace RTT { namespace OS {
00025     template <class T, class Alloc = std::allocator<T> >
00026     class local_allocator
00027     {
00028     public:
00029         typedef typename Alloc::value_type      value_type;
00030         typedef typename Alloc::pointer         pointer;
00031         typedef typename Alloc::const_pointer   const_pointer;
00032         typedef typename Alloc::reference       reference;
00033         typedef typename Alloc::const_reference const_reference;
00034         typedef typename Alloc::size_type       size_type;
00035         typedef typename Alloc::difference_type difference_type;
00036         //...
00037     public:
00038         pointer address(reference x) const {
00039             return Alloc().address(x);
00040         }
00041 
00042         const_pointer address(const_reference x) const {
00043             return Alloc().address(x);
00044         }
00045     public:
00046         pointer allocate(size_type n, const_pointer hint = 0) {
00047             pointer ret = 0;
00048             if (n == 0)
00049                 return ret;
00050             MutexLock lock( pool_lock );
00051             // if present in pool, return pool item
00052             std::pair<pool_it,pool_it> r = pool.equal_range( n );
00053             while ( r.first != r.second && r.first->second == 0  )
00054                 ++r.first;
00055             // if found, return item :
00056             if ( r.first != r.second ) {
00057                 ret = r.first->second;
00058                 r.first->second = 0; // clear out
00059                 //std::cerr << "Using grown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
00060                 return ret;
00061             }
00062 
00063             // fallback on allocator...
00064             // ret is still zero here
00065             pool.insert( typename pool_type::value_type(n,ret) );     // store free location.
00066             ret = this->_grow(n, hint);
00067             //std::cerr << "Allocated ungrown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
00068 
00069             return ret;
00070         }
00071 
00072         void deallocate(pointer p, size_type n) {
00073             MutexLock lock( pool_lock );
00074             std::pair<pool_it,pool_it> r = pool.equal_range( n );
00075 //             if ( find( r.first, r.second, typename pool_type::value_type(n,p) ) != r.second )
00076 //                 assert(false && "Do not deallocate twice !");
00077             while ( r.first != r.second && r.first->second != 0  )
00078                 ++r.first;
00079             // if found, store item :
00080             if ( r.first != r.second ) {
00081                 r.first->second = p;
00082                 //std::cerr << "Storing grown: "<< p <<" of size "<<n<<" in "<<typeid(p).name()<<std::endl;
00083                 return;
00084             }
00085             // if not found, we did not allocate it !
00086             //std::cerr << "Deallocating ungrown: "<<p << " of size "<<n<<" in "<<typeid(p).name()<<std::endl;
00087             this->_shrink(p,n);
00088         }
00089 
00090         size_type max_size() const {
00091             return Alloc().max_size();
00092         }
00093 
00094         void construct(pointer p, const value_type& x) {
00095             Alloc().construct(p, x);
00096         }
00097 
00098         void destroy(pointer p) { Alloc().destroy(p); }
00099 
00103         void grow(size_type n, const_pointer hint = 0) {
00104             MutexLock lock( pool_lock );
00105             pointer ret = this->_grow(n, hint);
00106             pool.insert( typename pool_type::value_type( n,ret ) );     // store mem location.
00107             //std::cerr << "Added   : "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
00108         }
00109 
00113         void shrink(size_type n) {
00114             if (n == 0)
00115                 return;
00116             MutexLock lock( pool_lock );
00117             std::pair<pool_it,pool_it> r = pool.equal_range( n );
00118             while ( r.first != r.second && r.first->second == 0  )
00119                 ++r.first;
00120             if ( r.first != r.second ) {
00121                 pointer t = r.first->second;
00122                 pool.erase( r.first ); // erase unused slot.
00123                 //std::cerr << "Removed: "<<t << " of size "<<n<<" in "<<typeid(t).name()<<std::endl;
00124                 _shrink(t,n);
00125                 return;
00126             }
00127             //std::cerr << "Unable to remove "<<n<<std::endl;
00128         }
00129     public:
00130         local_allocator() {}
00131         local_allocator(const local_allocator&) {}
00132         ~local_allocator() {}
00133         template <class U, class A>
00134         local_allocator(const local_allocator<U,A>&) {}
00135 
00136         template <class U>
00137         struct rebind { typedef local_allocator<U, typename Alloc::template rebind<U>::other > other; };
00138     private:
00139         Mutex pool_lock;
00143         pointer _grow(size_type n, const_pointer hint = 0) {
00144             return Alloc().allocate( n, hint );
00145         }
00146 
00147         void _shrink( pointer t, size_type n) {
00148             Alloc().deallocate( t, n);
00149         }
00150 
00151         void operator=(const local_allocator&);
00152 
00153         // the pool stores block-size/pointer pairs. Also uses Alloc for allocation.
00154         typedef std::multimap< size_t, pointer> pool_type;
00155         typedef typename pool_type::iterator       pool_it;
00156         typedef typename pool_type::const_iterator pool_cit;
00157         // stores blocks -> memory map for allocated memory.
00158         struct pool_wrapper_type : public pool_type {
00159             ~pool_wrapper_type() {
00160                 // free all memory.
00161                 typename pool_type::iterator it = this->begin();
00162                 for (; it != this->end(); ++it ) {
00163                     Alloc().deallocate(it->second, it->first );
00164                 }
00165             }
00166         };
00167         static pool_wrapper_type pool;
00168 
00169     };
00170 
00171     template< class T, class A>
00172     typename local_allocator<T,A>::pool_wrapper_type local_allocator<T,A>::pool;
00173 
00174 //     template< class T, class A>
00175 //     Mutex local_allocator<T,A>::pool_lock;
00176 
00177     template <class T, class A, class A2>
00178     inline bool operator==(const local_allocator<T,A>& ,
00179                            const local_allocator<T,A2>& ) {
00180         return false;
00181     }
00182 
00183     template <class T, class A, class A2>
00184     inline bool operator!=(const local_allocator<T,A>& ,
00185                            const local_allocator<T,A2>& ) {
00186         return true;
00187     }
00188 
00189     template <class T, class A>
00190     inline bool operator==(const local_allocator<T,A>& ,
00191                            const local_allocator<T,A>& ) {
00192         return true;;
00193     }
00194 
00195     template <class T, class A>
00196     inline bool operator!=(const local_allocator<T,A>&,
00197                            const local_allocator<T,A>&) {
00198         return false;
00199     }
00200 
00201     template<>
00202     class local_allocator<void>
00203     {
00204         typedef void    value_type;
00205         typedef void*       pointer;
00206         typedef const void* const_pointer;
00207 
00208         template <class U>
00209         struct rebind { typedef local_allocator<U> other; };
00210     };
00211 
00217     template <class T> class rt_allocator
00218     {
00219     public:
00220         typedef T                 value_type;
00221         typedef value_type*       pointer;
00222         typedef const value_type* const_pointer;
00223         typedef value_type&       reference;
00224         typedef const value_type& const_reference;
00225         typedef std::size_t       size_type;
00226         typedef std::ptrdiff_t    difference_type;
00227         //...
00228     public:
00229         pointer address(reference x) const {
00230             return &x;
00231         }
00232 
00233         const_pointer address(const_reference x) const {
00234             return &x;
00235         }
00236     public:
00237         pointer allocate(size_type n, const_pointer = 0) {
00238             void* p = oro_rt_malloc(n * sizeof(T));
00239             if (!p)
00240                 throw std::bad_alloc();
00241             return static_cast<pointer>(p);
00242         }
00243 
00244         void deallocate(pointer p, size_type) {
00245             oro_rt_free(p);
00246         }
00247 
00248         size_type max_size() const {
00249             return static_cast<size_type>(-1) / sizeof(value_type);
00250         }
00251 
00252         void construct(pointer p, const value_type& x) {
00253             new(p) value_type(x);
00254         }
00255 
00256         void destroy(pointer p) { p->~value_type(); }
00257 
00258     public:
00259         rt_allocator() {}
00260         rt_allocator(const rt_allocator&) {}
00261         ~rt_allocator() {}
00262         template <class U>
00263         rt_allocator(const rt_allocator<U>&) {}
00264 
00265         template <class U>
00266         struct rebind { typedef rt_allocator<U> other; };
00267     private:
00268         void operator=(const rt_allocator&);
00269     };
00270 
00271     template <class T>
00272     inline bool operator==(const rt_allocator<T>&,
00273                            const rt_allocator<T>&) {
00274         return true;
00275     }
00276 
00277     template <class T>
00278     inline bool operator!=(const rt_allocator<T>&,
00279                            const rt_allocator<T>&) {
00280         return false;
00281     }
00282 
00283     template<> class rt_allocator<void>
00284     {
00285         typedef void        value_type;
00286         typedef void*       pointer;
00287         typedef const void* const_pointer;
00288 
00289         template <class U>
00290         struct rebind { typedef rt_allocator<U> other; };
00291     };
00292 }}
00293 
00294 #endif
Generated on Thu Dec 23 13:22:38 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3