oro_allocator.hpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: Peter Soetens  Thu Oct 22 11:59:07 CEST 2009  oro_allocator.hpp
00003 
00004                         oro_allocator.hpp -  description
00005                            -------------------
00006     begin                : Thu October 22 2009
00007     copyright            : (C) 2009 Peter Soetens
00008     email                : peter@thesourcworks.com
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
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             // if present in pool, return pool item
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             // if found, return item :
00094             if ( r.first != r.second ) {
00095                 ret = r.first->second;
00096                 r.first->second = 0; // clear out
00097                 //std::cerr << "Using grown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
00098                 return ret;
00099             }
00100 
00101             // fallback on allocator...
00102             // ret is still zero here
00103             pool.insert( typename pool_type::value_type(n,ret) );     // store free location.
00104             ret = this->_grow(n, hint);
00105             //std::cerr << "Allocated ungrown: "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
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 //             if ( find( r.first, r.second, typename pool_type::value_type(n,p) ) != r.second )
00114 //                 assert(false && "Do not deallocate twice !");
00115             while ( r.first != r.second && r.first->second != 0  )
00116                 ++r.first;
00117             // if found, store item :
00118             if ( r.first != r.second ) {
00119                 r.first->second = p;
00120                 //std::cerr << "Storing grown: "<< p <<" of size "<<n<<" in "<<typeid(p).name()<<std::endl;
00121                 return;
00122             }
00123             // if not found, we did not allocate it !
00124             //std::cerr << "Deallocating ungrown: "<<p << " of size "<<n<<" in "<<typeid(p).name()<<std::endl;
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 ) );     // store mem location.
00145             //std::cerr << "Added   : "<< ret<<" of size "<<n<<" in "<<typeid(ret).name()<<std::endl;
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 ); // erase unused slot.
00161                 //std::cerr << "Removed: "<<t << " of size "<<n<<" in "<<typeid(t).name()<<std::endl;
00162                 _shrink(t,n);
00163                 return;
00164             }
00165             //std::cerr << "Unable to remove "<<n<<std::endl;
00166         }
00167     public:
00168         local_allocator() {}
00169         local_allocator(const local_allocator&) { /* Use default mutex and empty pool */ }
00170         ~local_allocator() {}
00171         template <class U, class A>
00172         local_allocator(const local_allocator<U,A>&) { /* Use default mutex and empty pool */ }
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&) { /* Keep existing mutex and pool. */ }
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         // the pool stores block-size/pointer pairs. Also uses Alloc for allocation.
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         // stores blocks -> memory map for allocated memory.
00197         struct pool_wrapper_type : public pool_type {
00198             ~pool_wrapper_type() {
00199                 // free all memory.
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


rtt
Author(s): RTT Developers
autogenerated on Sat Jun 8 2019 18:46:16