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
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
00056 if ( r.first != r.second ) {
00057 ret = r.first->second;
00058 r.first->second = 0;
00059
00060 return ret;
00061 }
00062
00063
00064
00065 pool.insert( typename pool_type::value_type(n,ret) );
00066 ret = this->_grow(n, hint);
00067
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
00076
00077 while ( r.first != r.second && r.first->second != 0 )
00078 ++r.first;
00079
00080 if ( r.first != r.second ) {
00081 r.first->second = p;
00082
00083 return;
00084 }
00085
00086
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 ) );
00107
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 );
00123
00124 _shrink(t,n);
00125 return;
00126 }
00127
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
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
00158 struct pool_wrapper_type : public pool_type {
00159 ~pool_wrapper_type() {
00160
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
00175
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