[DEBUG] coreect enable shared from this

This commit is contained in:
Edouard DUPIN 2016-07-20 21:43:14 +02:00
parent 91cde36e9a
commit cdba466118
8 changed files with 86 additions and 62 deletions

View File

@ -11,35 +11,35 @@ ememory::Counter::Counter(bool _fromWeak):
m_counterShared(1), m_counterShared(1),
m_counterWeak(0), m_counterWeak(0),
m_mutex() { m_mutex() {
EMEMORY_VERBOSE("new counter(" << _fromWeak << ")"); EMEMORY_DBG("new counter(" << _fromWeak << ")");
if (_fromWeak == true) { if (_fromWeak == true) {
m_counterShared = 0; m_counterShared = 0;
m_counterWeak = 1; m_counterWeak = 1;
} }
EMEMORY_VERBOSE(" ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG(" ==> w:" << m_counterWeak << " s:" << m_counterShared);
} }
ememory::Counter::~Counter() { ememory::Counter::~Counter() {
EMEMORY_VERBOSE("delete counter"); EMEMORY_DBG("delete counter");
} }
int64_t ememory::Counter::incrementShared(bool _fromWeak) { int64_t ememory::Counter::incrementShared(bool _fromWeak) {
int64_t out; int64_t out;
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
EMEMORY_VERBOSE("shared++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("shared++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
if (m_counterShared != 0 || _fromWeak == false) { if (m_counterShared != 0 || _fromWeak == false) {
m_counterShared++; m_counterShared++;
} }
out = m_counterShared; out = m_counterShared;
EMEMORY_VERBOSE("shared++ (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("shared++ (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
} }
return out; return out;
} }
ememory::Counter::remove ememory::Counter::decrementShared() { ememory::Counter::remove ememory::Counter::decrementShared() {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
EMEMORY_VERBOSE("shared-- (start) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("shared-- (start) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
if (m_counterShared != 0) { if (m_counterShared != 0) {
m_counterShared--; m_counterShared--;
} else { } else {
@ -48,14 +48,14 @@ ememory::Counter::remove ememory::Counter::decrementShared() {
} }
if (m_counterShared == 0) { if (m_counterShared == 0) {
if (m_counterWeak == 0) { if (m_counterWeak == 0) {
EMEMORY_VERBOSE("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
return ememory::Counter::remove::all; return ememory::Counter::remove::all;
} else { } else {
EMEMORY_VERBOSE("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
return ememory::Counter::remove::data; return ememory::Counter::remove::data;
} }
} }
EMEMORY_VERBOSE("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
return ememory::Counter::remove::none; return ememory::Counter::remove::none;
} }
@ -63,19 +63,17 @@ int64_t ememory::Counter::incrementWeak() {
int64_t out; int64_t out;
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
EMEMORY_VERBOSE("weak++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("weak++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
if (m_counterShared != 0) { m_counterWeak++;
m_counterWeak++;
}
out = m_counterWeak; out = m_counterWeak;
EMEMORY_VERBOSE("weak++ (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("weak++ (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
} }
return out; return out;
} }
ememory::Counter::remove ememory::Counter::decrementWeak() { ememory::Counter::remove ememory::Counter::decrementWeak() {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
EMEMORY_VERBOSE("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
if (m_counterWeak != 0) { if (m_counterWeak != 0) {
m_counterWeak--; m_counterWeak--;
} else { } else {
@ -84,10 +82,10 @@ ememory::Counter::remove ememory::Counter::decrementWeak() {
} }
if ( m_counterShared == 0 if ( m_counterShared == 0
&& m_counterWeak == 0) { && m_counterWeak == 0) {
EMEMORY_VERBOSE("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
return ememory::Counter::remove::counter; return ememory::Counter::remove::counter;
} }
EMEMORY_VERBOSE("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared); EMEMORY_DBG("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
return ememory::Counter::remove::none; return ememory::Counter::remove::none;
} }

View File

@ -12,9 +12,9 @@
namespace ememory { namespace ememory {
class EnableSharedFromThisBase {};
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
class EnableSharedFromThis { class EnableSharedFromThis : public ememory::EnableSharedFromThisBase {
friend class ememory::SharedPtr<EMEMORY_TYPE>;
private: private:
mutable ememory::WeakPtr<EMEMORY_TYPE> m_weakThis; mutable ememory::WeakPtr<EMEMORY_TYPE> m_weakThis;
protected: protected:

View File

@ -29,12 +29,12 @@ namespace ememory {
public: public:
template<class EMEMORY_TYPE2, template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value && std::is_base_of<ememory::EnableSharedFromThisBase, EMEMORY_TYPE2>::value
, int>::type = 0> , int>::type = 0>
SharedPtr(EMEMORY_TYPE2* _element); SharedPtr(EMEMORY_TYPE2* _element);
template<class EMEMORY_TYPE2, template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& !std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value && !std::is_base_of<ememory::EnableSharedFromThisBase, EMEMORY_TYPE2>::value
, int>::type = 0> , int>::type = 0>
SharedPtr(EMEMORY_TYPE2* _element); SharedPtr(EMEMORY_TYPE2* _element);
public: public:

View File

@ -32,6 +32,12 @@ namespace ememory {
#define EMEMORY_TODO(data) do { } while(false) #define EMEMORY_TODO(data) do { } while(false)
#endif #endif
#if 0
#define EMEMORY_DBG(data) EMEMORY_BASIC(5, data)
#else
#define EMEMORY_DBG(data) do { } while(false)
#endif
#define EMEMORY_HIDDEN(data) do { } while(false) #define EMEMORY_HIDDEN(data) do { } while(false)
#define EMEMORY_ASSERT(cond,data) \ #define EMEMORY_ASSERT(cond,data) \

View File

@ -11,7 +11,7 @@
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
ememory::EnableSharedFromThis<EMEMORY_TYPE>::EnableSharedFromThis() : ememory::EnableSharedFromThis<EMEMORY_TYPE>::EnableSharedFromThis() :
m_weakThis(static_cast<EMEMORY_TYPE*>(this)) { m_weakThis(static_cast<EMEMORY_TYPE*>(this)) {
EMEMORY_VERBOSE("create shared from this ..."); EMEMORY_DBG("create shared from this ...");
} }
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>

View File

@ -13,39 +13,37 @@
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
template<class EMEMORY_TYPE2, template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value && std::is_base_of<ememory::EnableSharedFromThisBase, EMEMORY_TYPE2>::value
, int>::type> , int>::type>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE2* _element): ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE2* _element):
m_element(_element), m_element(_element),
m_counter(nullptr), m_counter(nullptr),
m_deleter(createDeleter()) { m_deleter(createDeleter()) {
EMEMORY_VERBOSE("new shared"); EMEMORY_DBG("new shared");
if (m_element == nullptr) { if (m_element == nullptr) {
return; return;
} }
// check if the clas does not refer itself ... to get his own sharedPtr EMEMORY_DBG(" ==> get previous pointer");
ememory::EnableSharedFromThis<EMEMORY_TYPE2>* upperClass = static_cast<ememory::EnableSharedFromThis<EMEMORY_TYPE2>*>(m_element);
if (upperClass != nullptr) { m_counter = m_element->weakFromThis().getCounter();
EMEMORY_VERBOSE(" ==> get previous pointer"); if (m_counter != nullptr) {
m_counter = upperClass->m_weakThis.m_counter; m_counter->incrementShared();
if (m_counter != nullptr) {
m_counter->incrementShared();
}
return;
} }
return;
EMEMORY_ERROR("No counter on a shared ptr class (EnableSharedFromThis ==> this is bad"); EMEMORY_ERROR("No counter on a shared ptr class (EnableSharedFromThis ==> this is bad");
} }
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
template<class EMEMORY_TYPE2, template<class EMEMORY_TYPE2,
typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value typename std::enable_if< std::is_same<EMEMORY_TYPE2, EMEMORY_TYPE>::value
&& !std::is_base_of<ememory::EnableSharedFromThis<EMEMORY_TYPE2>, EMEMORY_TYPE2>::value && !std::is_base_of<ememory::EnableSharedFromThisBase, EMEMORY_TYPE2>::value
, int>::type> , int>::type>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE2* _element): ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE2* _element):
m_element(_element), m_element(_element),
m_counter(nullptr), m_counter(nullptr),
m_deleter(createDeleter()) { m_deleter(createDeleter()) {
EMEMORY_VERBOSE("new shared"); EMEMORY_DBG("new shared");
if (m_element == nullptr) { if (m_element == nullptr) {
return; return;
} }
@ -57,7 +55,7 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr():
m_element(nullptr), m_element(nullptr),
m_counter(nullptr), m_counter(nullptr),
m_deleter(createDeleter()) { m_deleter(createDeleter()) {
EMEMORY_VERBOSE("new shared"); EMEMORY_DBG("new shared");
} }
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
@ -65,7 +63,7 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(std::nullptr_t):
m_element(nullptr), m_element(nullptr),
m_counter(nullptr), m_counter(nullptr),
m_deleter(createDeleter()) { m_deleter(createDeleter()) {
EMEMORY_VERBOSE("new shared"); EMEMORY_DBG("new shared");
} }
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
@ -73,7 +71,7 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _obj, ememory::Counter
m_element(_obj), m_element(_obj),
m_counter(_counter), m_counter(_counter),
m_deleter(createDeleter()) { m_deleter(createDeleter()) {
EMEMORY_VERBOSE("new shared (from a cast)"); EMEMORY_DBG("new shared (from a cast)");
if (_obj == nullptr) { if (_obj == nullptr) {
m_counter = nullptr; m_counter = nullptr;
return; return;
@ -83,7 +81,7 @@ ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _obj, ememory::Counter
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::~SharedPtr() { ememory::SharedPtr<EMEMORY_TYPE>::~SharedPtr() {
EMEMORY_VERBOSE("delete shared"); EMEMORY_DBG("delete shared");
reset(); reset();
} }
@ -133,6 +131,7 @@ ememory::SharedPtr<EMEMORY_TYPE>& ememory::SharedPtr<EMEMORY_TYPE>::operator= (s
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(ememory::SharedPtr<EMEMORY_TYPE>&& _obj) { ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(ememory::SharedPtr<EMEMORY_TYPE>&& _obj) {
EMEMORY_INFO("move operator ... " << int64_t(_obj.m_counter));
m_element = _obj.m_element; m_element = _obj.m_element;
m_counter = _obj.m_counter; m_counter = _obj.m_counter;
m_deleter = _obj.m_deleter; m_deleter = _obj.m_deleter;
@ -189,7 +188,7 @@ void ememory::SharedPtr<EMEMORY_TYPE>::reset() {
m_deleter = nullptr; m_deleter = nullptr;
return; return;
} }
EMEMORY_VERBOSE("reset sharedPtr (start)"); EMEMORY_DBG("reset sharedPtr (start)");
ememory::Counter::remove rmData = m_counter->decrementShared(); ememory::Counter::remove rmData = m_counter->decrementShared();
switch(rmData) { switch(rmData) {
case ememory::Counter::remove::all: case ememory::Counter::remove::all:
@ -216,7 +215,7 @@ void ememory::SharedPtr<EMEMORY_TYPE>::reset() {
m_deleter = nullptr; m_deleter = nullptr;
m_counter = nullptr; m_counter = nullptr;
m_element = nullptr; m_element = nullptr;
EMEMORY_VERBOSE("reset sharedPtr (stop)"); EMEMORY_DBG("reset sharedPtr (stop)");
} }
template<typename EMEMORY_TYPE> template<typename EMEMORY_TYPE>
@ -333,21 +332,21 @@ namespace ememory {
SharedPtr(std::nullptr_t): SharedPtr(std::nullptr_t):
m_element(nullptr), m_element(nullptr),
m_counter(nullptr) { m_counter(nullptr) {
EMEMORY_VERBOSE("new shared<void>"); EMEMORY_DBG("new shared<void>");
} }
SharedPtr(): SharedPtr():
m_element(nullptr), m_element(nullptr),
m_counter(nullptr) { m_counter(nullptr) {
EMEMORY_VERBOSE("new shared<void>"); EMEMORY_DBG("new shared<void>");
} }
~SharedPtr() { ~SharedPtr() {
EMEMORY_VERBOSE("delete shared"); EMEMORY_DBG("delete shared");
reset(); reset();
} }
SharedPtr(void* _obj, ememory::Counter* _counter): SharedPtr(void* _obj, ememory::Counter* _counter):
m_element(_obj), m_element(_obj),
m_counter(_counter) { m_counter(_counter) {
EMEMORY_VERBOSE("new shared (from a cast)"); EMEMORY_DBG("new shared (from a cast)");
if (_obj == nullptr) { if (_obj == nullptr) {
m_counter = nullptr; m_counter = nullptr;
return; return;
@ -401,7 +400,7 @@ namespace ememory {
m_element = nullptr; // in case ... m_element = nullptr; // in case ...
return; return;
} }
EMEMORY_VERBOSE("reset sharedPtr (start)"); EMEMORY_DBG("reset sharedPtr (start)");
ememory::Counter::remove rmData = m_counter->decrementShared(); ememory::Counter::remove rmData = m_counter->decrementShared();
switch(rmData) { switch(rmData) {
case ememory::Counter::remove::all: case ememory::Counter::remove::all:
@ -419,7 +418,7 @@ namespace ememory {
} }
m_counter = nullptr; m_counter = nullptr;
m_element = nullptr; m_element = nullptr;
EMEMORY_VERBOSE("reset sharedPtr (stop)"); EMEMORY_DBG("reset sharedPtr (stop)");
} }
int64_t useCount() const { int64_t useCount() const {
if (m_counter == nullptr) { if (m_counter == nullptr) {

View File

@ -28,7 +28,7 @@ template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(EMEMORY_TYPE* _element): ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(EMEMORY_TYPE* _element):
m_element(_element), m_element(_element),
m_counter(nullptr) { m_counter(nullptr) {
EMEMORY_VERBOSE("new weak"); EMEMORY_DBG("new weak");
if (m_element == nullptr) { if (m_element == nullptr) {
return; return;
} }

View File

@ -8,22 +8,43 @@
#include <ememory/memory.h> #include <ememory/memory.h>
#include "main.h" #include "main.h"
namespace testESFT {
class TestClassBase : public ememory::EnableSharedFromThis<TestClassBase> {
public:
TestClassBase() {
EMEMORY_INFO("create TestClassBase");
}
~TestClassBase() {
EMEMORY_INFO("delete TestClassBase");
}
};
class TestClass : public testESFT::TestClassBase {
public:
TestClass() {
EMEMORY_INFO("create TestClass");
}
~TestClass() {
EMEMORY_INFO("delete TestClass");
}
};
}
class testClass : public ememory::EnableSharedFromThis<testClass> { TEST(TestEnableSharedFromThis, testClassBase) {
public: ememory::SharedPtr<testESFT::TestClassBase> data = ememory::makeShared<testESFT::TestClassBase>();
testClass() {
EMEMORY_INFO("create TestClass");
}
~testClass() {
EMEMORY_INFO("delete TestClass");
}
};
TEST(TestEnableSharedFromThis, base) {
ememory::SharedPtr<testClass> data = ememory::makeShared<testClass>();
EXPECT_EQ(data.useCount(), 1); EXPECT_EQ(data.useCount(), 1);
ememory::WeakPtr<testClass> dataWeak = data; ememory::WeakPtr<testESFT::TestClassBase> dataWeak = data;
EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(dataWeak.useCount(), 1);
data.reset();
EXPECT_EQ(data.useCount(), 0);
EXPECT_EQ(dataWeak.useCount(), 0);
}
TEST(TestEnableSharedFromThis, testClass) {
ememory::SharedPtr<testESFT::TestClass> data = ememory::makeShared<testESFT::TestClass>();
EXPECT_EQ(data.useCount(), 1);
ememory::WeakPtr<testESFT::TestClass> dataWeak = data;
EXPECT_EQ(data.useCount(), 1); EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(dataWeak.useCount(), 1); EXPECT_EQ(dataWeak.useCount(), 1);
data.reset(); data.reset();