From e9dc4c8c0f9b789e047676a8fa3f97443f28ca86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Sun, 12 Nov 2017 11:45:50 +0100 Subject: [PATCH] implement Poco::SharedPtr using std::shared_ptr --- Foundation/include/Poco/SharedPtr.h | 218 ++++++--------------- Foundation/testsuite/src/SharedPtrTest.cpp | 34 ++-- 2 files changed, 82 insertions(+), 170 deletions(-) diff --git a/Foundation/include/Poco/SharedPtr.h b/Foundation/include/Poco/SharedPtr.h index 5efe8e99b1..0f1bea4443 100644 --- a/Foundation/include/Poco/SharedPtr.h +++ b/Foundation/include/Poco/SharedPtr.h @@ -20,147 +20,67 @@ #include "Poco/Foundation.h" #include "Poco/Exception.h" -#include "Poco/AtomicCounter.h" +#include #include namespace Poco { -class ReferenceCounter - /// Simple ReferenceCounter object, does not delete itself when count reaches 0. -{ -public: - ReferenceCounter(): _cnt(1) - { - } - - void duplicate() - { - ++_cnt; - } - - int release() - { - return --_cnt; - } - - int referenceCount() const - { - return _cnt.value(); - } - -private: - AtomicCounter _cnt; -}; - - +//@ deprecated template -class ReleasePolicy - /// The default release policy for SharedPtr, which - /// simply uses the delete operator to delete an object. -{ -public: - static void release(C* pObj) - /// Delete the object. - /// Note that pObj can be 0. - { - delete pObj; - } -}; - - -template -class ReleaseArrayPolicy - /// The release policy for SharedPtr holding arrays. +class SharedPtr + /// As of POCO C++ Libraries Release 2.0, SharedPtr is a small wrapper around + /// std::shared_ptr, providing basic backwards compatibility to the 1.x SharedPtr + /// implementation. + /// + /// Note: ReleasePolicy is no longer supported. + /// + /// SharedPtr will be removed in a future release. New code should use + /// std::shared_ptr and existing code should be changed to use std::shared_ptr + /// instead of Poco::SharedPtr. { public: - static void release(C* pObj) - /// Delete the object. - /// Note that pObj can be 0. + SharedPtr() { - delete [] pObj; } -}; - -template > -class SharedPtr - /// SharedPtr is a "smart" pointer for classes implementing - /// reference counting based garbage collection. - /// SharedPtr is thus similar to AutoPtr. Unlike the - /// AutoPtr template, which can only be used with - /// classes that support reference counting, SharedPtr - /// can be used with any class. For this to work, a - /// SharedPtr manages a reference count for the object - /// it manages. - /// - /// SharedPtr works in the following way: - /// If an SharedPtr is assigned an ordinary pointer to - /// an object (via the constructor or the assignment operator), - /// it takes ownership of the object and the object's reference - /// count is initialized to one. - /// If the SharedPtr is assigned another SharedPtr, the - /// object's reference count is incremented by one. - /// The destructor of SharedPtr decrements the object's - /// reference count by one and deletes the object if the - /// reference count reaches zero. - /// SharedPtr supports dereferencing with both the -> - /// and the * operator. An attempt to dereference a null - /// SharedPtr results in a NullPointerException being thrown. - /// SharedPtr also implements all relational operators and - /// a cast operator in case dynamic casting of the encapsulated data types - /// is required. -{ -public: - SharedPtr(): _pCounter(new RC), _ptr(0) + SharedPtr(C* ptr): + _ptr(ptr) { } - SharedPtr(C* ptr) - try: - _pCounter(new RC), + SharedPtr(const std::shared_ptr& ptr): _ptr(ptr) { } - catch (...) + + template + SharedPtr(const SharedPtr& ptr): + _ptr(std::dynamic_pointer_cast(ptr.shared_ptr())) { - RP::release(ptr); } - template - SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(const_cast(ptr.get())) + SharedPtr(const SharedPtr& ptr): + _ptr(ptr._ptr) { - _pCounter->duplicate(); } - SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr) + SharedPtr(SharedPtr&& ptr): + _ptr(std::move(ptr._ptr)) { - _pCounter->duplicate(); } ~SharedPtr() { - try - { - release(); - } - catch (...) - { - poco_unexpected(); - } } SharedPtr& assign(C* ptr) { - if (get() != ptr) - { - SharedPtr tmp(ptr); - swap(tmp); - } + _ptr.reset(ptr); return *this; } - + SharedPtr& assign(const SharedPtr& ptr) { if (&ptr != this) @@ -170,9 +90,9 @@ class SharedPtr } return *this; } - - template - SharedPtr& assign(const SharedPtr& ptr) + + template + SharedPtr& assign(const SharedPtr& ptr) { if (ptr.get() != _ptr) { @@ -192,8 +112,8 @@ class SharedPtr return assign(ptr); } - template - SharedPtr& operator = (const SharedPtr& ptr) + template + SharedPtr& operator = (const SharedPtr& ptr) { return assign(ptr); } @@ -201,11 +121,10 @@ class SharedPtr void swap(SharedPtr& ptr) { std::swap(_ptr, ptr._ptr); - std::swap(_pCounter, ptr._pCounter); } template - SharedPtr cast() const + SharedPtr cast() const /// Casts the SharedPtr via a dynamic cast to the given type. /// Returns an SharedPtr containing NULL if the cast fails. /// Example: (assume class Sub: public Super) @@ -213,22 +132,33 @@ class SharedPtr /// SharedPtr sub = super.cast(); /// poco_assert (sub.get()); { - Other* pOther = dynamic_cast(_ptr); - if (pOther) - return SharedPtr(_pCounter, pOther); - return SharedPtr(); + return SharedPtr(std::dynamic_pointer_cast(_ptr)); } template - SharedPtr unsafeCast() const + SharedPtr unsafeCast() const /// Casts the SharedPtr via a static cast to the given type. /// Example: (assume class Sub: public Super) /// SharedPtr super(new Sub()); /// SharedPtr sub = super.unsafeCast(); /// poco_assert (sub.get()); { - Other* pOther = static_cast(_ptr); - return SharedPtr(_pCounter, pOther); + return SharedPtr(std::static_pointer_cast(_ptr)); + } + + operator std::shared_ptr() + { + return _ptr; + } + + const std::shared_ptr& shared_ptr() const + { + return _ptr; + } + + std::shared_ptr& shared_ptr() + { + return _ptr; } C* operator -> () @@ -253,22 +183,22 @@ class SharedPtr C* get() { - return _ptr; + return _ptr.get(); } const C* get() const { - return _ptr; + return _ptr.get(); } operator C* () { - return _ptr; + return _ptr.get(); } - + operator const C* () const { - return _ptr; + return _ptr.get(); } bool operator ! () const @@ -370,10 +300,10 @@ class SharedPtr { return get() >= ptr; } - - int referenceCount() const + + long referenceCount() const { - return _pCounter->referenceCount(); + return _ptr.use_count(); } protected: @@ -382,40 +312,16 @@ class SharedPtr if (!_ptr) throw NullPointerException(); - return _ptr; - } - - void release() - { - poco_assert_dbg (_pCounter); - int i = _pCounter->release(); - if (i == 0) - { - RP::release(_ptr); - _ptr = 0; - - delete _pCounter; - _pCounter = 0; - } - } - - SharedPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr) - /// for cast operation - { - poco_assert_dbg (_pCounter); - _pCounter->duplicate(); + return _ptr.get(); } protected: - RC* _pCounter; - C* _ptr; - - template friend class SharedPtr; + std::shared_ptr _ptr; }; -template -inline void swap(SharedPtr& p1, SharedPtr& p2) +template +inline void swap(SharedPtr& p1, SharedPtr& p2) { p1.swap(p2); } diff --git a/Foundation/testsuite/src/SharedPtrTest.cpp b/Foundation/testsuite/src/SharedPtrTest.cpp index c9a2973afa..f3bbe4be75 100644 --- a/Foundation/testsuite/src/SharedPtrTest.cpp +++ b/Foundation/testsuite/src/SharedPtrTest.cpp @@ -28,27 +28,27 @@ namespace { ++_count; } - + virtual ~TestObject() { --_count; } - + const std::string& data() { return _data; } - + static int count() { return _count; } - + private: std::string _data; static int _count; }; - + int TestObject::_count = 0; class DerivedObject: public TestObject @@ -62,7 +62,7 @@ namespace { return _number; } - + private: int _number; }; @@ -104,27 +104,27 @@ void SharedPtrTest::testSharedPtr() assert (ptr2 == pTO2); assert (ptr3.get() == pTO1); assert (ptr3 == pTO1); - + assert (ptr1 == pTO1); assert (ptr1 != pTO2); assert (ptr1 < pTO2); assert (ptr1 <= pTO2); assert (ptr2 > pTO1); assert (ptr2 >= pTO1); - + assert (ptr1 == ptr3); assert (ptr1 != ptr2); assert (ptr1 < ptr2); assert (ptr1 <= ptr2); assert (ptr2 > ptr1); assert (ptr2 >= ptr1); - + ptr1.swap(ptr2); assert (ptr2 < ptr1); ptr2.swap(ptr1); assert ((ptr1->data() == "one" && ptr2->data() == "two") || (ptr1->data() == "two" && ptr2->data() == "one")); - + try { assert (ptr4->data() == "four"); @@ -133,28 +133,34 @@ void SharedPtrTest::testSharedPtr() catch (NullPointerException&) { } - + assert (!(ptr4 == ptr1)); assert (!(ptr4 == ptr2)); assert (ptr4 != ptr1); assert (ptr4 != ptr2); - + ptr4 = ptr2; assert (ptr4 == ptr2); assert (!(ptr4 != ptr2)); - + assert (TestObject::count() == 2); ptr1 = 0; ptr2 = 0; ptr3 = 0; ptr4 = 0; assert (TestObject::count() == 0); - + { SharedPtr ptr = new TestObject(""); assert (TestObject::count() == 1); } assert (TestObject::count() == 0); + + std::shared_ptr stdp(std::make_shared("")); + Poco::SharedPtr ptr5(stdp); + std::shared_ptr stdp2 = ptr5; + + assert (stdp == stdp2); }