00001 #pragma ident "$Id: MemoryUtils.hpp 2937 2011-10-23 19:23:33Z yanweignss $"
00002
00008 #ifndef GPSTK_MEMORYUTILS_HPP
00009 #define GPSTK_MEMORYUTILS_HPP
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <list>
00034 #include <algorithm>
00035 #include <cassert>
00036
00037 namespace gpstk
00038 {
00039
00040
00041
00042
00043
00044
00045
00046
00047
00049 template <class C>
00050 class ReleasePolicy
00051 {
00052 public:
00053 static void release(C* pObj) { delete pObj; }
00054 };
00055
00057 template <class C>
00058 class ReleaseArrayPolicy
00059 {
00060 public:
00061 static void release(C* pObj) { delete [] pObj; }
00062 };
00063
00065 template <class C>
00066 class ReleaseCustomizePolicy
00067 {
00068 public:
00069 static void release(C* pObj) { if(pObj) pObj->release(); }
00070 };
00071
00072
00073
00075 template < class C, class RP = ReleasePolicy<C> >
00076 class AutoReleasePool
00077 {
00078 public:
00079 AutoReleasePool()
00080 { }
00081
00082 ~AutoReleasePool()
00083 { release();}
00084
00085 void add(C* pObject)
00086 { if (pObject) _list.push_back(pObject); }
00087
00088 void release()
00089 {
00090 while (!_list.empty())
00091 {
00092 RP::release(_list.front());
00093 _list.pop_front();
00094 }
00095 }
00096
00097 protected:
00098
00099 std::list<C*> _list;
00100
00101 };
00102
00103
00104 class ReferenceCounter
00105 {
00106 public:
00107 ReferenceCounter(): counter(1)
00108 { }
00109
00110 void duplicate()
00111 { ++counter; }
00112
00113 int release()
00114 { return (--counter <= 0) ? 0 : counter; }
00115
00116 int referenceCount() const
00117 { return counter; }
00118
00119 private:
00120 long counter;
00121 };
00122
00148 template <class C, class RP = ReleasePolicy<C>, class RC = ReferenceCounter >
00149 class AutoPtr
00150 {
00151 public:
00152 AutoPtr(): _pCounter(new RC), _ptr(0)
00153 {}
00154
00155 AutoPtr(C* ptr): _pCounter(new RC), _ptr(ptr)
00156 {}
00157
00158 template <class Other, class OtherRP>
00159 AutoPtr(const AutoPtr<Other, RC, OtherRP>& ptr)
00160 : _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get()))
00161 { _pCounter->duplicate(); }
00162
00163 AutoPtr(const AutoPtr& ptr)
00164 : _pCounter(ptr._pCounter), _ptr(ptr._ptr)
00165 { _pCounter->duplicate(); }
00166
00167 ~AutoPtr()
00168 { release(); }
00169
00170 AutoPtr& assign(C* ptr)
00171 {
00172 if (get() != ptr)
00173 {
00174 RC* pTmp = new RC;
00175 release();
00176 _pCounter = pTmp;
00177 _ptr = ptr;
00178 }
00179 return *this;
00180 }
00181
00182 AutoPtr& assign(const AutoPtr& ptr)
00183 {
00184 if (&ptr != this)
00185 {
00186 AutoPtr tmp(ptr);
00187 swap(tmp);
00188 }
00189 return *this;
00190 }
00191
00192 template <class Other, class OtherRP>
00193 AutoPtr& assign(const AutoPtr<Other, RC, OtherRP>& ptr)
00194 {
00195 if (ptr.get() != _ptr)
00196 {
00197 AutoPtr tmp(ptr);
00198 swap(tmp);
00199 }
00200 return *this;
00201 }
00202
00203 AutoPtr& operator = (C* ptr)
00204 { return assign(ptr); }
00205
00206 AutoPtr& operator = (const AutoPtr& ptr)
00207 { return assign(ptr); }
00208
00209 template <class Other, class OtherRP>
00210 AutoPtr& operator = (const AutoPtr<Other, RC, OtherRP>& ptr)
00211 { return assign<Other>(ptr); }
00212
00213 void swap(AutoPtr& ptr)
00214 {
00215 std::swap(_ptr, ptr._ptr);
00216 std::swap(_pCounter, ptr._pCounter);
00217 }
00218
00219 template <class Other>
00220 AutoPtr<Other, RC, RP> cast() const
00221 {
00222 Other* pOther = dynamic_cast<Other*>(_ptr);
00223 if (pOther)
00224 return AutoPtr<Other, RC, RP>(_pCounter, pOther);
00225 return AutoPtr<Other, RC, RP>();
00226 }
00227
00228 template <class Other>
00229 AutoPtr<Other, RC, RP> unsafeCast() const
00230 {
00231 Other* pOther = static_cast<Other*>(_ptr);
00232 return AutoPtr<Other, RC, RP>(_pCounter, pOther);
00233 }
00234
00235 C* operator -> ()
00236 { return deref(); }
00237
00238 const C* operator -> () const
00239 { return deref(); }
00240
00241 C& operator * ()
00242 { return *deref(); }
00243
00244 const C& operator * () const
00245 { return *deref(); }
00246
00247 C* get()
00248 { return _ptr; }
00249
00250 const C* get() const
00251 { return _ptr; }
00252
00253 operator C* ()
00254 { return _ptr; }
00255
00256 operator const C* () const
00257 { return _ptr; }
00258
00259 bool operator ! () const
00260 { return _ptr == 0; }
00261
00262 bool isNull() const
00263 { return _ptr == 0; }
00264
00265 bool operator == (const AutoPtr& ptr) const
00266 { return get() == ptr.get(); }
00267
00268 bool operator == (const C* ptr) const
00269 { return get() == ptr; }
00270
00271 bool operator == (C* ptr) const
00272 { return get() == ptr; }
00273
00274 bool operator != (const AutoPtr& ptr) const
00275 { return get() != ptr.get(); }
00276
00277 bool operator != (const C* ptr) const
00278 { return get() != ptr; }
00279
00280 bool operator != (C* ptr) const
00281 { return get() != ptr; }
00282
00283 bool operator < (const AutoPtr& ptr) const
00284 { return get() < ptr.get(); }
00285
00286 bool operator < (const C* ptr) const
00287 { return get() < ptr; }
00288
00289 bool operator < (C* ptr) const
00290 { return get() < ptr; }
00291
00292 bool operator <= (const AutoPtr& ptr) const
00293 { return get() <= ptr.get(); }
00294
00295 bool operator <= (const C* ptr) const
00296 { return get() <= ptr; }
00297
00298 bool operator <= (C* ptr) const
00299 { return get() <= ptr; }
00300
00301 bool operator > (const AutoPtr& ptr) const
00302 { return get() > ptr.get(); }
00303
00304 bool operator > (const C* ptr) const
00305 { return get() > ptr; }
00306
00307 bool operator > (C* ptr) const
00308 { return get() > ptr; }
00309
00310 bool operator >= (const AutoPtr& ptr) const
00311 { return get() >= ptr.get(); }
00312
00313 bool operator >= (const C* ptr) const
00314 { return get() >= ptr; }
00315
00316 bool operator >= (C* ptr) const
00317 { return get() >= ptr; }
00318
00319 int referenceCount() const
00320 { return _pCounter->referenceCount(); }
00321
00322 private:
00323 C* deref() const
00324 {
00325 if (!_ptr) GPSTK_THROW(NullPointerException("Try access a pointer."));
00326
00327 return _ptr;
00328 }
00329
00330 void release()
00331 {
00332 int i = _pCounter->release();
00333 if (i == 0)
00334 {
00335 RP::release(_ptr);
00336 _ptr = 0;
00337
00338 delete _pCounter;
00339 _pCounter = 0;
00340 }
00341 }
00342
00343 AutoPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr)
00344 {
00345 _pCounter->duplicate();
00346 }
00347
00348 private:
00349 RC* _pCounter;
00350 C* _ptr;
00351
00352 template <class OtherC, class OtherRC, class OtherRP> friend class AutoPtr;
00353 };
00354
00355
00356 template <class C, class RC, class RP>
00357 inline void swap(AutoPtr<C, RC, RP>& p1, AutoPtr<C, RC, RP>& p2)
00358 {
00359 p1.swap(p2);
00360 }
00361
00362
00363 template <class T>
00364 class Buffer
00365 {
00366 public:
00367 Buffer(std::size_t size):_size(size),_ptr(new T[size]){}
00368
00369 ~Buffer(){ if(_ptr) delete [] _ptr;}
00370
00371 std::size_t size() const {return _size;}
00372
00373 T* begin() { return _ptr; }
00374
00375 const T* begin() const{return _ptr;}
00376
00377 T* end(){return _ptr + _size;}
00378
00379 const T* end() const { return _ptr + _size;}
00380
00381 T& operator [] (std::size_t index)
00382 {
00383 if(index<0 || index>=_size)
00384 {
00385 GPSTK_THROW(Exception("The input index is out of range."));
00386 }
00387
00388 return _ptr[index];
00389 }
00390
00391 const T& operator [] (std::size_t index) const
00392 {
00393 if(index<0 || index>=_size)
00394 {
00395 GPSTK_THROW(Exception("The input index is out of range."));
00396 }
00397
00398 return _ptr[index];
00399 }
00400
00401 private:
00402 Buffer();
00403 Buffer(const Buffer&);
00404 Buffer& operator = (const Buffer&);
00405
00406 std::size_t _size;
00407 T* _ptr;
00408 };
00409
00410
00411 }
00412
00413
00414 #endif //GPSTK_MEMORYUTILS_HPP
00415