[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_counterWeak(0),
m_mutex() {
EMEMORY_VERBOSE("new counter(" << _fromWeak << ")");
EMEMORY_DBG("new counter(" << _fromWeak << ")");
if (_fromWeak == true) {
m_counterShared = 0;
m_counterWeak = 1;
}
EMEMORY_VERBOSE(" ==> w:" << m_counterWeak << " s:" << m_counterShared);
EMEMORY_DBG(" ==> w:" << m_counterWeak << " s:" << m_counterShared);
}
ememory::Counter::~Counter() {
EMEMORY_VERBOSE("delete counter");
EMEMORY_DBG("delete counter");
}
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);
EMEMORY_DBG("shared++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
if (m_counterShared != 0 || _fromWeak == false) {
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;
}
ememory::Counter::remove ememory::Counter::decrementShared() {
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) {
m_counterShared--;
} else {
@ -48,14 +48,14 @@ ememory::Counter::remove ememory::Counter::decrementShared() {
}
if (m_counterShared == 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;
} 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;
}
}
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;
}
@ -63,19 +63,17 @@ int64_t ememory::Counter::incrementWeak() {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
EMEMORY_VERBOSE("weak++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared);
if (m_counterShared != 0) {
m_counterWeak++;
}
EMEMORY_DBG("weak++ (start) ==> w:" << m_counterWeak << " s:" << m_counterShared << " " << int64_t(this));
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;
}
ememory::Counter::remove ememory::Counter::decrementWeak() {
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) {
m_counterWeak--;
} else {
@ -84,10 +82,10 @@ ememory::Counter::remove ememory::Counter::decrementWeak() {
}
if ( m_counterShared == 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;
}
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;
}

View File

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

View File

@ -29,12 +29,12 @@ namespace ememory {
public:
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
&& std::is_base_of<ememory::EnableSharedFromThisBase, 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
&& !std::is_base_of<ememory::EnableSharedFromThisBase, EMEMORY_TYPE2>::value
, int>::type = 0>
SharedPtr(EMEMORY_TYPE2* _element);
public:

View File

@ -32,6 +32,12 @@ namespace ememory {
#define EMEMORY_TODO(data) do { } while(false)
#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_ASSERT(cond,data) \

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 ...");
EMEMORY_DBG("create shared from this ...");
}
template<typename EMEMORY_TYPE>

View File

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

View File

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

View File

@ -8,22 +8,43 @@
#include <ememory/memory.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> {
public:
testClass() {
EMEMORY_INFO("create TestClass");
}
~testClass() {
EMEMORY_INFO("delete TestClass");
}
};
TEST(TestEnableSharedFromThis, base) {
ememory::SharedPtr<testClass> data = ememory::makeShared<testClass>();
TEST(TestEnableSharedFromThis, testClassBase) {
ememory::SharedPtr<testESFT::TestClassBase> data = ememory::makeShared<testESFT::TestClassBase>();
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(dataWeak.useCount(), 1);
data.reset();