00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef Foundation_SharedPtr_INCLUDED
00040 #define Foundation_SharedPtr_INCLUDED
00041
00042
00043 #include "Poco/Foundation.h"
00044 #include "Poco/Exception.h"
00045 #include "Poco/AtomicCounter.h"
00046 #include <algorithm>
00047
00048
00049 namespace Poco {
00050
00051
00052 class ReferenceCounter
00054 {
00055 public:
00056 ReferenceCounter(): _cnt(1)
00057 {
00058 }
00059
00060 void duplicate()
00061 {
00062 ++_cnt;
00063 }
00064
00065 int release()
00066 {
00067 return --_cnt;
00068 }
00069
00070 int referenceCount() const
00071 {
00072 return _cnt.value();
00073 }
00074
00075 private:
00076 AtomicCounter _cnt;
00077 };
00078
00079
00080 template <class C>
00081 class ReleasePolicy
00084 {
00085 public:
00086 static void release(C* pObj)
00089 {
00090 delete pObj;
00091 }
00092 };
00093
00094
00095 template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >
00096 class SharedPtr
00122 {
00123 public:
00124 SharedPtr(): _pCounter(new RC), _ptr(0)
00125 {
00126 }
00127
00128 SharedPtr(C* ptr): _pCounter(new RC), _ptr(ptr)
00129 {
00130 }
00131
00132 template <class Other, class OtherRP>
00133 SharedPtr(const SharedPtr<Other, RC, OtherRP>& ptr): _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get()))
00134 {
00135 _pCounter->duplicate();
00136 }
00137
00138 SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr)
00139 {
00140 _pCounter->duplicate();
00141 }
00142
00143 ~SharedPtr()
00144 {
00145 release();
00146 }
00147
00148 SharedPtr& assign(C* ptr)
00149 {
00150 if (get() != ptr)
00151 {
00152 RC* pTmp = new RC;
00153 release();
00154 _pCounter = pTmp;
00155 _ptr = ptr;
00156 }
00157 return *this;
00158 }
00159
00160 SharedPtr& assign(const SharedPtr& ptr)
00161 {
00162 if (&ptr != this)
00163 {
00164 SharedPtr tmp(ptr);
00165 swap(tmp);
00166 }
00167 return *this;
00168 }
00169
00170 template <class Other, class OtherRP>
00171 SharedPtr& assign(const SharedPtr<Other, RC, OtherRP>& ptr)
00172 {
00173 if (ptr.get() != _ptr)
00174 {
00175 SharedPtr tmp(ptr);
00176 swap(tmp);
00177 }
00178 return *this;
00179 }
00180
00181 SharedPtr& operator = (C* ptr)
00182 {
00183 return assign(ptr);
00184 }
00185
00186 SharedPtr& operator = (const SharedPtr& ptr)
00187 {
00188 return assign(ptr);
00189 }
00190
00191 template <class Other, class OtherRP>
00192 SharedPtr& operator = (const SharedPtr<Other, RC, OtherRP>& ptr)
00193 {
00194 return assign<Other>(ptr);
00195 }
00196
00197 void swap(SharedPtr& ptr)
00198 {
00199 std::swap(_ptr, ptr._ptr);
00200 std::swap(_pCounter, ptr._pCounter);
00201 }
00202
00203 template <class Other>
00204 SharedPtr<Other, RC, RP> cast() const
00211 {
00212 Other* pOther = dynamic_cast<Other*>(_ptr);
00213 if (pOther)
00214 return SharedPtr<Other, RC, RP>(_pCounter, pOther);
00215 return SharedPtr<Other, RC, RP>();
00216 }
00217
00218 template <class Other>
00219 SharedPtr<Other, RC, RP> unsafeCast() const
00225 {
00226 Other* pOther = static_cast<Other*>(_ptr);
00227 return SharedPtr<Other, RC, RP>(_pCounter, pOther);
00228 }
00229
00230 C* operator -> ()
00231 {
00232 return deref();
00233 }
00234
00235 const C* operator -> () const
00236 {
00237 return deref();
00238 }
00239
00240 C& operator * ()
00241 {
00242 return *deref();
00243 }
00244
00245 const C& operator * () const
00246 {
00247 return *deref();
00248 }
00249
00250 C* get()
00251 {
00252 return _ptr;
00253 }
00254
00255 const C* get() const
00256 {
00257 return _ptr;
00258 }
00259
00260 operator C* ()
00261 {
00262 return _ptr;
00263 }
00264
00265 operator const C* () const
00266 {
00267 return _ptr;
00268 }
00269
00270 bool operator ! () const
00271 {
00272 return _ptr == 0;
00273 }
00274
00275 bool isNull() const
00276 {
00277 return _ptr == 0;
00278 }
00279
00280 bool operator == (const SharedPtr& ptr) const
00281 {
00282 return get() == ptr.get();
00283 }
00284
00285 bool operator == (const C* ptr) const
00286 {
00287 return get() == ptr;
00288 }
00289
00290 bool operator == (C* ptr) const
00291 {
00292 return get() == ptr;
00293 }
00294
00295 bool operator != (const SharedPtr& ptr) const
00296 {
00297 return get() != ptr.get();
00298 }
00299
00300 bool operator != (const C* ptr) const
00301 {
00302 return get() != ptr;
00303 }
00304
00305 bool operator != (C* ptr) const
00306 {
00307 return get() != ptr;
00308 }
00309
00310 bool operator < (const SharedPtr& ptr) const
00311 {
00312 return get() < ptr.get();
00313 }
00314
00315 bool operator < (const C* ptr) const
00316 {
00317 return get() < ptr;
00318 }
00319
00320 bool operator < (C* ptr) const
00321 {
00322 return get() < ptr;
00323 }
00324
00325 bool operator <= (const SharedPtr& ptr) const
00326 {
00327 return get() <= ptr.get();
00328 }
00329
00330 bool operator <= (const C* ptr) const
00331 {
00332 return get() <= ptr;
00333 }
00334
00335 bool operator <= (C* ptr) const
00336 {
00337 return get() <= ptr;
00338 }
00339
00340 bool operator > (const SharedPtr& ptr) const
00341 {
00342 return get() > ptr.get();
00343 }
00344
00345 bool operator > (const C* ptr) const
00346 {
00347 return get() > ptr;
00348 }
00349
00350 bool operator > (C* ptr) const
00351 {
00352 return get() > ptr;
00353 }
00354
00355 bool operator >= (const SharedPtr& ptr) const
00356 {
00357 return get() >= ptr.get();
00358 }
00359
00360 bool operator >= (const C* ptr) const
00361 {
00362 return get() >= ptr;
00363 }
00364
00365 bool operator >= (C* ptr) const
00366 {
00367 return get() >= ptr;
00368 }
00369
00370 int referenceCount() const
00371 {
00372 return _pCounter->referenceCount();
00373 }
00374
00375 private:
00376 C* deref() const
00377 {
00378 if (!_ptr)
00379 throw NullPointerException();
00380
00381 return _ptr;
00382 }
00383
00384 void release()
00385 {
00386 poco_assert_dbg (_pCounter);
00387 int i = _pCounter->release();
00388 if (i == 0)
00389 {
00390 RP::release(_ptr);
00391 _ptr = 0;
00392
00393 delete _pCounter;
00394 _pCounter = 0;
00395 }
00396 }
00397
00398 SharedPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr)
00400 {
00401 poco_assert_dbg (_pCounter);
00402 _pCounter->duplicate();
00403 }
00404
00405 private:
00406 RC* _pCounter;
00407 C* _ptr;
00408
00409 template <class OtherC, class OtherRC, class OtherRP> friend class SharedPtr;
00410 };
00411
00412
00413 template <class C, class RC, class RP>
00414 inline void swap(SharedPtr<C, RC, RP>& p1, SharedPtr<C, RC, RP>& p2)
00415 {
00416 p1.swap(p2);
00417 }
00418
00419
00420 }
00421
00422
00423 #endif // Foundation_SharedPtr_INCLUDED