[DEV] SharedPtr work ... but now I have the constness of sub element when SharedPtr is const (good pointinstead of the std)

This commit is contained in:
Edouard DUPIN 2016-07-14 23:58:54 +02:00
parent b271ad15ad
commit 39e7d4103e
13 changed files with 292 additions and 37 deletions

View File

@ -23,12 +23,12 @@ ememory::Counter::~Counter() {
EMEMORY_VERBOSE("delete counter");
}
int64_t ememory::Counter::incrementShared() {
int64_t ememory::Counter::incrementShared(bool _fromWeak) {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
EMEMORY_VERBOSE("shared++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared);
if (m_counterShared != 0) {
if (m_counterShared != 0 || _fromWeak == false) {
m_counterShared++;
}
out = m_counterShared;

View File

@ -27,7 +27,7 @@ namespace ememory {
public:
Counter(bool _fromWeak=false);
~Counter();
int64_t incrementShared();
int64_t incrementShared(bool _fromWeak=false);
ememory::Counter::remove decrementShared();
int64_t incrementWeak();
ememory::Counter::remove decrementWeak();

View File

@ -22,7 +22,9 @@ namespace ememory {
virtual ~EnableSharedFromThis() = default;
public:
ememory::SharedPtr<EMEMORY_TYPE> sharedFromThis();
const ememory::SharedPtr<EMEMORY_TYPE> sharedFromThis() const;
ememory::WeakPtr<EMEMORY_TYPE> weakFromThis();
const ememory::WeakPtr<EMEMORY_TYPE> weakFromThis() const;
};
}

View File

@ -9,9 +9,11 @@
#include <mutex>
#include <ememory/debug.h>
#include <ememory/Counter.h>
#include <ememory/EnableSharedFromThis.h>
namespace ememory {
template<typename> class WeakPtr;
template<typename> class EnableSharedFromThis;
// limited implementation of actual shared pointer (only 1 instance allowed, can be promoted though)
template<typename EMEMORY_TYPE>
class SharedPtr {
@ -20,26 +22,50 @@ namespace ememory {
EMEMORY_TYPE* m_element;
ememory::Counter* m_counter;
public:
SharedPtr(EMEMORY_TYPE* _element);
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value
, int>::type = 0>
SharedPtr(EMEMORY_TYPE2* _element);
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& !std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value
, int>::type = 0>
SharedPtr(EMEMORY_TYPE2* _element);
public:
SharedPtr();
~SharedPtr();
SharedPtr(const SharedPtr& _obj);
SharedPtr& operator= (const SharedPtr& _obj);
SharedPtr(SharedPtr&& _obj);
SharedPtr(EMEMORY_TYPE* _obj, ememory::Counter* _counter);
SharedPtr(const SharedPtr<EMEMORY_TYPE>& _obj);
SharedPtr& operator= (const SharedPtr<EMEMORY_TYPE>& _obj);
SharedPtr& operator= (std::nullptr_t);
SharedPtr(SharedPtr<EMEMORY_TYPE>&& _obj);
public:
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type = 0>
SharedPtr(const SharedPtr<EMEMORY_TYPE2>& _obj);
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type = 0>
SharedPtr& operator= (const SharedPtr<EMEMORY_TYPE2>& _obj);
public:
void reset();
int64_t useCount() const;
bool operator == (std::nullptr_t);
bool operator==(const SharedPtr& _obj) const;
bool operator != (std::nullptr_t);
bool operator!=(const SharedPtr& _obj) const;
bool operator == (std::nullptr_t) const;
bool operator==(const SharedPtr<EMEMORY_TYPE>& _obj) const;
bool operator != (std::nullptr_t) const;
bool operator!=(const SharedPtr<EMEMORY_TYPE>& _obj) const;
const EMEMORY_TYPE* get() const;
EMEMORY_TYPE* get();
const EMEMORY_TYPE* operator->() const;
EMEMORY_TYPE* operator->();
const EMEMORY_TYPE& operator*() const;
EMEMORY_TYPE& operator*();
void swap(SharedPtr& _obj);
void swap(SharedPtr<EMEMORY_TYPE>& _obj);
ememory::Counter* getCounter() const {
return m_counter;
}
};
}

View File

@ -16,6 +16,7 @@ namespace ememory {
template<typename EMEMORY_TYPE>
class WeakPtr {
friend class EnableSharedFromThis<EMEMORY_TYPE>;
friend class SharedPtr<EMEMORY_TYPE>;
private:
EMEMORY_TYPE* m_element;
ememory::Counter* m_counter;
@ -30,13 +31,31 @@ namespace ememory {
WeakPtr(WeakPtr&& _obj);
WeakPtr(const SharedPtr<EMEMORY_TYPE>& _obj);
WeakPtr<EMEMORY_TYPE>& operator= (const SharedPtr<EMEMORY_TYPE>& _obj);
WeakPtr<EMEMORY_TYPE>& operator= (std::nullptr_t);
public:
/*
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type = 0>
WeakPtr(const WeakPtr<EMEMORY_TYPE2>& _obj);
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type = 0>
WeakPtr& operator= (const WeakPtr<EMEMORY_TYPE2>& _obj);
*/
public:
void reset();
int useCount() const;
bool expired() const;
ememory::SharedPtr<EMEMORY_TYPE> lock();
bool operator == (const WeakPtr& _obj);
bool operator == (std::nullptr_t);
bool operator==(const WeakPtr& _obj);
bool operator==(std::nullptr_t) const;
bool operator!=(const WeakPtr& _obj);
bool operator!=(std::nullptr_t) const;
void swap(WeakPtr& _obj);
ememory::Counter* getCounter() const {
return m_counter;
}
};
}

View File

@ -11,7 +11,7 @@
template<typename EMEMORY_TYPE>
ememory::EnableSharedFromThis<EMEMORY_TYPE>::EnableSharedFromThis() :
m_weakThis(static_cast<EMEMORY_TYPE*>(this)) {
EMEMORY_VERBOSE("create shared from this ...");
}
template<typename EMEMORY_TYPE>
@ -19,8 +19,18 @@ ememory::SharedPtr<EMEMORY_TYPE> ememory::EnableSharedFromThis<EMEMORY_TYPE>::sh
return m_weakThis.lock();
}
template<typename EMEMORY_TYPE>
const ememory::SharedPtr<EMEMORY_TYPE> ememory::EnableSharedFromThis<EMEMORY_TYPE>::sharedFromThis() const{
return m_weakThis.lock();
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE> ememory::EnableSharedFromThis<EMEMORY_TYPE>::weakFromThis() {
return m_weakThis;
}
template<typename EMEMORY_TYPE>
const ememory::WeakPtr<EMEMORY_TYPE> ememory::EnableSharedFromThis<EMEMORY_TYPE>::weakFromThis() const {
return m_weakThis;
}

View File

@ -11,7 +11,11 @@
#include <ememory/WeakPtr.h>
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _element):
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value
, int>::type>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE2* _element):
m_element(_element),
m_counter(nullptr) {
EMEMORY_VERBOSE("new shared");
@ -19,19 +23,24 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _element):
return;
}
// check if the clas does not refer itself ... to get his own sharedPtr
ememory::EnableSharedFromThis<EMEMORY_TYPE> upperClass = static_cast<ememory::EnableSharedFromThis<EMEMORY_TYPE>*>(m_element);
ememory::EnableSharedFromThis<EMEMORY_TYPE2>* upperClass = static_cast<ememory::EnableSharedFromThis<EMEMORY_TYPE2>*>(m_element);
if (upperClass != nullptr) {
m_counter = upperClass->m_weakThis;
EMEMORY_VERBOSE(" ==> get previous pointer");
m_counter = upperClass->m_weakThis.m_counter;
if (m_counter != nullptr) {
m_counter->incrementShared();
}
} else {
m_counter = new ememory::Counter(false);
return;
}
EMEMORY_ERROR("No counter on a shared ptr class (EnableSharedFromThis ==> this is bad");
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _element):
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& !std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value
, int>::type>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE2* _element):
m_element(_element),
m_counter(nullptr) {
EMEMORY_VERBOSE("new shared");
@ -48,6 +57,18 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr():
EMEMORY_VERBOSE("new shared");
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _obj, ememory::Counter* _counter):
m_element(_obj),
m_counter(_counter) {
EMEMORY_VERBOSE("new shared (from a cast)");
if (_obj == nullptr) {
m_counter = nullptr;
return;
}
m_counter->incrementShared();
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::~SharedPtr() {
EMEMORY_VERBOSE("delete shared");
@ -87,6 +108,13 @@ ememory::SharedPtr<EMEMORY_TYPE>& ememory::SharedPtr<EMEMORY_TYPE>::operator= (c
return *this;
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>& ememory::SharedPtr<EMEMORY_TYPE>::operator= (std::nullptr_t) {
reset();
return *this;
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(ememory::SharedPtr<EMEMORY_TYPE>&& _obj) {
m_element = _obj.m_element;
@ -95,6 +123,45 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(ememory::SharedPtr<EMEMORY_TYPE>&& _
_obj.m_counter = nullptr;
}
template<typename EMEMORY_TYPE>
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(const ememory::SharedPtr<EMEMORY_TYPE2>& _obj):
m_element(const_cast<EMEMORY_TYPE2*>(_obj.get())),
m_counter(const_cast<ememory::Counter*>(_obj.getCounter())) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementShared();
}
template<typename EMEMORY_TYPE>
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type>
ememory::SharedPtr<EMEMORY_TYPE>& ememory::SharedPtr<EMEMORY_TYPE>::operator= (const SharedPtr<EMEMORY_TYPE2>& _obj) {
m_element = const_cast<EMEMORY_TYPE2*>(_obj.get());
m_counter = const_cast<ememory::Counter*>(_obj.getCounter());
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return *this;
}
if (m_counter == nullptr) {
return *this;
}
m_counter->incrementShared();
return *this;
}
template<typename EMEMORY_TYPE>
void ememory::SharedPtr<EMEMORY_TYPE>::reset() {
if(m_counter == nullptr) {
@ -131,7 +198,7 @@ int64_t ememory::SharedPtr<EMEMORY_TYPE>::useCount() const {
}
template<typename EMEMORY_TYPE>
bool ememory::SharedPtr<EMEMORY_TYPE>::operator == (std::nullptr_t) {
bool ememory::SharedPtr<EMEMORY_TYPE>::operator == (std::nullptr_t) const {
return m_counter == nullptr;
}
@ -141,7 +208,7 @@ bool ememory::SharedPtr<EMEMORY_TYPE>::operator==(const SharedPtr& _obj) const {
}
template<typename EMEMORY_TYPE>
bool ememory::SharedPtr<EMEMORY_TYPE>::operator != (std::nullptr_t) {
bool ememory::SharedPtr<EMEMORY_TYPE>::operator != (std::nullptr_t) const {
return m_counter != nullptr;
}

View File

@ -66,6 +66,12 @@ ememory::WeakPtr<EMEMORY_TYPE>& ememory::WeakPtr<EMEMORY_TYPE>::operator= (const
return *this;
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>& ememory::WeakPtr<EMEMORY_TYPE>::operator= (std::nullptr_t) {
reset();
return *this;
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(ememory::WeakPtr<EMEMORY_TYPE>&& _obj) {
m_element = _obj.m_element;
@ -108,6 +114,44 @@ ememory::WeakPtr<EMEMORY_TYPE>& ememory::WeakPtr<EMEMORY_TYPE>::operator= (const
return *this;
}
/*
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type>
WeakPtr(const WeakPtr<EMEMORY_TYPE2>& _obj):
m_element(_obj.m_element),
m_counter(_obj.getCounter()) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementWeak();
}
template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_base_of<EMEMORY_TYPE, EMEMORY_TYPE2>::value
, int>::type>
WeakPtr& operator= (const WeakPtr<EMEMORY_TYPE2>& _obj) {
m_element = _obj.m_element;
m_counter = _obj.getCounter();
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return *this;
}
if (m_counter == nullptr) {
return *this;
}
m_counter->incrementWeak();
return *this;
}
*/
template<typename EMEMORY_TYPE>
void ememory::WeakPtr<EMEMORY_TYPE>::reset() {
if(m_counter == nullptr) {
@ -154,7 +198,7 @@ ememory::SharedPtr<EMEMORY_TYPE> ememory::WeakPtr<EMEMORY_TYPE>::lock() {
if (m_counter == nullptr) {
return out;
}
int64_t count = m_counter->incrementShared();
int64_t count = m_counter->incrementShared(true);
if (count == 0) {
return out;
}
@ -164,15 +208,25 @@ ememory::SharedPtr<EMEMORY_TYPE> ememory::WeakPtr<EMEMORY_TYPE>::lock() {
}
template<typename EMEMORY_TYPE>
bool ememory::WeakPtr<EMEMORY_TYPE>::operator == (const ememory::WeakPtr<EMEMORY_TYPE>& _obj) {
bool ememory::WeakPtr<EMEMORY_TYPE>::operator==(const ememory::WeakPtr<EMEMORY_TYPE>& _obj) {
return m_counter == _obj.m_counter;
}
template<typename EMEMORY_TYPE>
bool ememory::WeakPtr<EMEMORY_TYPE>::operator == (std::nullptr_t) {
bool ememory::WeakPtr<EMEMORY_TYPE>::operator==(std::nullptr_t) const {
return m_counter == nullptr;
}
template<typename EMEMORY_TYPE>
bool ememory::WeakPtr<EMEMORY_TYPE>::operator!=(const ememory::WeakPtr<EMEMORY_TYPE>& _obj) {
return m_counter != _obj.m_counter;
}
template<typename EMEMORY_TYPE>
bool ememory::WeakPtr<EMEMORY_TYPE>::operator!=(std::nullptr_t) const {
return m_counter != nullptr;
}
template<typename EMEMORY_TYPE>
void ememory::WeakPtr<EMEMORY_TYPE>::swap(ememory::WeakPtr<EMEMORY_TYPE>& _obj) {
EMEMORY_TYPE* tmpE = m_element;

View File

@ -12,8 +12,36 @@
#include <ememory/EnableSharedFromThis.h>
namespace ememory {
template<class EMEMORY_TYPE, typename... EMEMORY_ARGS>
static ememory::SharedPtr<EMEMORY_TYPE> makeShared(EMEMORY_ARGS && ...args) {
return ememory::SharedPtr<EMEMORY_TYPE>(new EMEMORY_TYPE(std::forward<EMEMORY_ARGS>(args)...));
static ememory::SharedPtr<EMEMORY_TYPE> makeShared(EMEMORY_ARGS && ..._args) {
return ememory::SharedPtr<EMEMORY_TYPE>(new EMEMORY_TYPE(std::forward<EMEMORY_ARGS>(_args)...));
}
template<class EMEMORY_TYPE_CAST, class EMEMORY_TYPE>
inline ememory::SharedPtr<EMEMORY_TYPE_CAST> dynamicPointerCast(ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
return ememory::SharedPtr<EMEMORY_TYPE_CAST>(dynamic_cast<EMEMORY_TYPE_CAST*>(_obj.get()), _obj.getCounter());
}
template<class EMEMORY_TYPE_CAST, class EMEMORY_TYPE>
inline const ememory::SharedPtr<EMEMORY_TYPE_CAST> dynamicPointerCast(const ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
return ememory::SharedPtr<EMEMORY_TYPE_CAST>(dynamic_cast<EMEMORY_TYPE_CAST*>(_obj.get()), _obj.getCounter());
}
template<class EMEMORY_TYPE_CAST, class EMEMORY_TYPE>
inline ememory::SharedPtr<EMEMORY_TYPE_CAST> staticPointerCast(ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
return ememory::SharedPtr<EMEMORY_TYPE_CAST>(static_cast<EMEMORY_TYPE_CAST*>(_obj.get()), _obj.getCounter());
}
template<class EMEMORY_TYPE_CAST, class EMEMORY_TYPE>
inline const ememory::SharedPtr<EMEMORY_TYPE_CAST> staticPointerCast(const ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
return ememory::SharedPtr<EMEMORY_TYPE_CAST>(static_cast<EMEMORY_TYPE_CAST*>(_obj.get()), _obj.getCounter());
}
template<class EMEMORY_TYPE_CAST, class EMEMORY_TYPE>
inline ememory::SharedPtr<EMEMORY_TYPE_CAST> reinterpretPointerCast(ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
return ememory::SharedPtr<EMEMORY_TYPE_CAST>(reinterpret_cast<EMEMORY_TYPE_CAST*>(_obj.get()), _obj.getCounter());
}
template<class EMEMORY_TYPE_CAST, class EMEMORY_TYPE>
inline const ememory::SharedPtr<EMEMORY_TYPE_CAST> reinterpretPointerCast(const ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
return ememory::SharedPtr<EMEMORY_TYPE_CAST>(reinterpret_cast<EMEMORY_TYPE_CAST*>(_obj.get()), _obj.getCounter());
}
}

View File

@ -0,0 +1,55 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <gtest/gtest.h>
#include <ememory/memory.h>
#include "main.h"
namespace testEnableCast {
class testClass {
public:
testClass() {
EMEMORY_INFO("create TestClass");
}
virtual ~testClass() {
EMEMORY_INFO("delete TestClass");
}
};
class testClassChild : public testEnableCast::testClass {
public:
testClassChild() {
EMEMORY_INFO("create TestClassChild");
}
~testClassChild() {
EMEMORY_INFO("delete TestClassChild");
}
};
}
TEST(TestEnableCast, base) {
ememory::SharedPtr<testEnableCast::testClassChild> dataChild = ememory::makeShared<testEnableCast::testClassChild>();
EXPECT_EQ(dataChild.useCount(), 1);
ememory::SharedPtr<testEnableCast::testClass> data = dataChild;
EXPECT_EQ(dataChild.useCount(), 2);
EXPECT_EQ(data.useCount(), 2);
ememory::SharedPtr<testEnableCast::testClassChild> dataChildStatic = ememory::staticPointerCast<testEnableCast::testClassChild>(data);
EXPECT_EQ(dataChild.useCount(), 3);
EXPECT_EQ(data.useCount(), 3);
EXPECT_EQ(dataChildStatic.useCount(), 3);
ememory::SharedPtr<testEnableCast::testClassChild> dataChildDynamic = ememory::dynamicPointerCast<testEnableCast::testClassChild>(data);
EXPECT_EQ(dataChild.useCount(), 4);
EXPECT_EQ(data.useCount(), 4);
EXPECT_EQ(dataChildStatic.useCount(), 4);
EXPECT_EQ(dataChildDynamic.useCount(), 4);
ememory::SharedPtr<testEnableCast::testClassChild> dataChildReinterpret = ememory::reinterpretPointerCast<testEnableCast::testClassChild>(data);
EXPECT_EQ(dataChild.useCount(), 5);
EXPECT_EQ(data.useCount(), 5);
EXPECT_EQ(dataChildStatic.useCount(), 5);
EXPECT_EQ(dataChildDynamic.useCount(), 5);
EXPECT_EQ(dataChildReinterpret.useCount(), 5);
}

View File

@ -1,8 +1,6 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2014, Edouard DUPIN, all right reserved
*
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/

View File

@ -1,8 +1,6 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2014, Edouard DUPIN, all right reserved
*
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/

View File

@ -1,8 +1,6 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2014, Edouard DUPIN, all right reserved
*
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/