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