[DEV] shared ptr work but not EnableSharedFrom this (missing cast too)

This commit is contained in:
Edouard DUPIN 2016-07-14 00:48:53 +02:00
parent 5cbaabf049
commit b271ad15ad
19 changed files with 903 additions and 407 deletions

View File

@ -0,0 +1,120 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <ememory/Counter.h>
#include <ememory/debug.h>
ememory::Counter::Counter(bool _fromWeak):
m_counterShared(1),
m_counterWeak(0),
m_mutex() {
EMEMORY_VERBOSE("new counter(" << _fromWeak << ")");
if (_fromWeak == true) {
m_counterShared = 0;
m_counterWeak = 1;
}
EMEMORY_VERBOSE(" ==> w:" << m_counterWeak << " s:" << m_counterShared);
}
ememory::Counter::~Counter() {
EMEMORY_VERBOSE("delete counter");
}
int64_t ememory::Counter::incrementShared() {
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) {
m_counterShared++;
}
out = m_counterShared;
EMEMORY_VERBOSE("shared++ (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
}
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);
if (m_counterShared != 0) {
m_counterShared--;
} else {
EMEMORY_ERROR("try to decrement a SharedPtr with no more element in RefCount");
return ememory::Counter::remove::none;
}
if (m_counterShared == 0) {
if (m_counterWeak == 0) {
EMEMORY_VERBOSE("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
return ememory::Counter::remove::all;
} else {
EMEMORY_VERBOSE("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
return ememory::Counter::remove::data;
}
}
EMEMORY_VERBOSE("shared-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
return ememory::Counter::remove::none;
}
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++;
}
out = m_counterWeak;
EMEMORY_VERBOSE("weak++ (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
}
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);
if (m_counterWeak != 0) {
m_counterWeak--;
} else {
EMEMORY_ERROR("try to decrement a WeakPtr with no more element in RefCount");
return ememory::Counter::remove::none;
}
if ( m_counterShared == 0
&& m_counterWeak == 0) {
EMEMORY_VERBOSE("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
return ememory::Counter::remove::counter;
}
EMEMORY_VERBOSE("weak-- (stop) ==> w:" << m_counterWeak << " s:" << m_counterShared);
return ememory::Counter::remove::none;
}
int64_t ememory::Counter::getCountWeak() const {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
out = m_counterWeak;
}
return out;
}
int64_t ememory::Counter::getCountShared() const {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
out = m_counterShared;
}
return out;
}
int64_t ememory::Counter::getCount() const {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
out = m_counterWeak + m_counterShared;
}
return out;
}

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <mutex>
// define type : uintXX_t and intXX_t
#define __STDC_LIMIT_MACROS
// note in android include the macro of min max are overwitten
#include <stdint.h>
namespace ememory {
class Counter {
public:
enum class remove {
none,
data,
counter,
all
};
private:
int64_t m_counterShared;
int64_t m_counterWeak;
mutable std::mutex m_mutex;
public:
Counter(bool _fromWeak=false);
~Counter();
int64_t incrementShared();
ememory::Counter::remove decrementShared();
int64_t incrementWeak();
ememory::Counter::remove decrementWeak();
int64_t getCountWeak() const;
int64_t getCountShared() const;
int64_t getCount() const;
};
}

View File

@ -0,0 +1,30 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <mutex>
#include <ememory/SharedPtr.h>
#include <ememory/WeakPtr.h>
namespace ememory {
template<typename EMEMORY_TYPE>
class EnableSharedFromThis {
friend class ememory::SharedPtr<EMEMORY_TYPE>;
private:
ememory::WeakPtr<EMEMORY_TYPE> m_weakThis;
protected:
EnableSharedFromThis();
virtual ~EnableSharedFromThis() = default;
public:
ememory::SharedPtr<EMEMORY_TYPE> sharedFromThis();
ememory::WeakPtr<EMEMORY_TYPE> weakFromThis();
};
}
#include <ememory/details/EnableSharedFromThis.hxx>

View File

@ -1,394 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <mutex>
#include <ememory/debug.h>
#include <ememory/Counter.h>
namespace ememoryTMP {
namespace ememory {
template<typename> class WeakPtr;
class Counter {
public:
enum class remove {
none,
data,
counter,
all
}
private:
int64_t m_counterShared;
int64_t m_counterWeak;
mutable std::mutex m_mutex;
public:
Counter():
m_counterShared(0),
m_counterWeak(0),
m_element(nullptr) {
}
int64_t incrementShared() {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_counterShared != 0) {
m_counterShared++;
}
out = m_counterShared;
}
return out;
}
ememoryTMP::Counter::remove decrementShared() {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_counterShared != 0) {
m_counterShared--;
} else {
EMEMORY_ERROR("try to decrement a SharedPtr with no more element in RefCount");
return ememoryTMP::Counter::remove::none;
}
if (m_counterShared == 0) {
if (m_counterWeak == 0) {
return ememoryTMP::Counter::remove::all;
} else {
return ememoryTMP::Counter::remove::data;
}
}
return ememoryTMP::Counter::remove::none;
}
int64_t incrementWeak() {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_counterWeak != 0) {
m_counterWeak++;
}
out = m_counterWeak;
}
return out;
}
ememoryTMP::Counter::remove decrementWeak() {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_counterWeak != 0) {
m_counterWeak--;
} else {
EMEMORY_ERROR("try to decrement a WeakPtr with no more element in RefCount");
return ememoryTMP::Counter::remove::none;
}
if ( m_counterShared == 0
&& m_counterWeak == 0) {
return ememoryTMP::Counter::remove::counter;
}
return ememoryTMP::Counter::remove::none;
}
/*
void kill() {
m_element = nullptr;
if(m_counter == 0) {
delete this;
}
}
*/
int64_t getCountWeak() const {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
out = m_counterWeak;
}
return out;
}
int64_t getCountShared() const {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
out = m_counterShared;
}
return out;
}
int64_t getCount() const {
int64_t out;
{
std::unique_lock<std::mutex> lock(m_mutex);
out = m_counterWeak + m_counterShared;
}
return out;
}
};
// limited implementation of actual shared pointer (only 1 instance allowed, can be promoted though)
template<typename EMEMORY_TYPE>
class SharedPtr {
friend class WeakPtr<EMEMORY_TYPE>;
private:
EMEMORY_TYPE* m_element;
ememoryTMP::Counter* m_counter;
private:
SharedPtr(EMEMORY_TYPE* _element):
m_element(_element),
m_counter(nullptr) {
if (m_element == nullptr) {
return;
}
m_counter = new ememoryTMP::Counter();
m_counter->incrementShared();
}
ememory::Counter* m_counter;
public:
SharedPtr():
m_element(nullptr),
m_counter(nullptr) {
}
~SharedPtr() {
reset();
}
SharedPtr(const SharedPtr& _obj):
m_element(_obj.m_element),
m_counter(_obj.m_counter) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementShared();
};
SharedPtr& operator= (const SharedPtr& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
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;
}
SharedPtr(SharedPtr&& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = nullptr;
_obj.m_counter = nullptr;
}
void reset() {
if(m_counter == nullptr) {
m_element = nullptr; // in case ...
return;
}
ememoryTMP::Counter::remove rmData = m_counter->decrementShared();
switch(rmData) {
case ememoryTMP::Counter::remove::all:
delete m_counter;
delete m_element;
break;
case ememoryTMP::Counter::remove::data:
delete m_element;
break;
case ememoryTMP::Counter::remove::counter:
delete m_counter;
break;
case ememoryTMP::Counter::remove::none:
break;
}
m_counter = nullptr;
m_element = nullptr;
}
int useCount() const {
if (m_counter == nullptr) {
return 0;
}
return m_counter->getCountShared();
}
bool operator == (std::nullptr_t) {
return m_counter == nullptr;
}
bool operator==(const SharedPtr& _obj) const {
return m_counter == _obj.m_counter;
}
bool operator != (std::nullptr_t) {
return m_counter != nullptr;
}
bool operator!=(const SharedPtr& _obj) const {
return m_counter != _obj.m_counter;
}
const EMEMORY_TYPE* get() const {
return m_element;
}
EMEMORY_TYPE* get() {
return m_element;
}
const EMEMORY_TYPE& operator->() const {
return *m_element;
}
EMEMORY_TYPE& operator->() {
return *m_element;
}
const EMEMORY_TYPE& operator*() const {
return *m_element;
}
EMEMORY_TYPE& operator*() {
return *m_element;
}
void swap(WeakPtr& _obj) {
EMEMORY_TYPE* tmpE = m_element;
ememoryTMP::Counter* tmpC = m_counter;
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = tmpE;
_obj.m_counter = tmpC;
}
};
template<class EMEMORY_TYPE, typename... EMEMORY_ARGS>
static ememoryTMP::SharedPtr makeShared(EMEMORY_ARGS && ...args) {
// TODO : Enable shared from this ...
return ememoryTMP::SharedPtr(new EMEMORY_TYPE(std::forward<EMEMORY_ARGS>(args)...));
}
template<typename EMEMORY_TYPE>
class WeakPtr {
private:
EMEMORY_TYPE* m_element;
ememoryTMP::Counter* m_counter;
SharedPtr(EMEMORY_TYPE* _element);
public:
WeakPtr():
m_element(nullptr),
m_counter(nullptr) {
}
~WeakPtr() {
reset();
}
WeakPtr(const WeakPtr& _obj):
m_element(_obj.m_element),
m_counter(_obj.m_counter) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementWeak();
};
WeakPtr& operator= (const WeakPtr& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
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;
}
WeakPtr(WeakPtr&& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = nullptr;
_obj.m_counter = nullptr;
}
WeakPtr(const SharedPtr& _obj):
m_element(_obj.m_element),
m_counter(_obj.m_counter) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementWeak();
};
WeakPtr& operator= (const WeakPtr& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
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;
}
void reset() {
if(m_counter == nullptr) {
m_element = nullptr; // in case ...
return;
}
ememoryTMP::Counter::remove rmData = m_counter->decrementWeak();
switch(rmData) {
case ememoryTMP::Counter::remove::all:
EMEMORY_ERROR("in WeakPtr request remove all (impossible case ...)");
break;
case ememoryTMP::Counter::remove::data:
EMEMORY_ERROR("in WeakPtr request remove all (impossible case ...)");
break;
case ememoryTMP::Counter::remove::counter:
delete m_counter;
break;
case ememoryTMP::Counter::remove::none:
break;
}
m_counter = nullptr;
m_element = nullptr;
}
int useCount() const {
if (m_counter == nullptr) {
return 0;
}
return m_counter->getCountShared();
}
bool expired() const {
if (m_counter == nullptr) {
return true;
}
return m_counter.getCountShared() != 0;
}
elemoryTMP::SharedPtr lock() {
elemoryTMP::SharedPtr out;
if (m_counter == nullptr) {
return out;
}
int64_t count = m_counter.incrementShared();
if (count == 0) {
return out;
}
out.m_counter = m_counter;
out.m_element = m_element;
return std::move(out);
}
bool operator == (const WeakPtr& _obj) {
return m_counter == _obj.m_counter;
}
bool operator == (std::nullptr_t) {
return m_counter == nullptr;
}
void swap(WeakPtr& _obj) {
EMEMORY_TYPE* tmpE = m_element;
ememoryTMP::Counter* tmpC = m_counter;
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = tmpE;
_obj.m_counter = tmpC;
}
SharedPtr();
~SharedPtr();
SharedPtr(const SharedPtr& _obj);
SharedPtr& operator= (const SharedPtr& _obj);
SharedPtr(SharedPtr&& _obj);
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;
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);
};
}
#include <ememory/details/SharedPtr.hxx>

View File

@ -0,0 +1,43 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <mutex>
#include <ememory/debug.h>
#include <ememory/Counter.h>
namespace ememory {
template<typename> class SharedPtr;
template<typename> class EnableSharedFromThis;
template<typename EMEMORY_TYPE>
class WeakPtr {
friend class EnableSharedFromThis<EMEMORY_TYPE>;
private:
EMEMORY_TYPE* m_element;
ememory::Counter* m_counter;
public:
WeakPtr();
private:
WeakPtr(EMEMORY_TYPE* _element); // this is only for enable shared from this ...
public:
~WeakPtr();
WeakPtr(const WeakPtr<EMEMORY_TYPE>& _obj);
WeakPtr<EMEMORY_TYPE>& operator= (const WeakPtr<EMEMORY_TYPE>& _obj);
WeakPtr(WeakPtr&& _obj);
WeakPtr(const SharedPtr<EMEMORY_TYPE>& _obj);
WeakPtr<EMEMORY_TYPE>& operator= (const SharedPtr<EMEMORY_TYPE>& _obj);
void reset();
int useCount() const;
bool expired() const;
ememory::SharedPtr<EMEMORY_TYPE> lock();
bool operator == (const WeakPtr& _obj);
bool operator == (std::nullptr_t);
void swap(WeakPtr& _obj);
};
}
#include <ememory/details/WeakPtr.hxx>

View File

@ -14,7 +14,7 @@ namespace ememory {
int32_t getLogId();
};
#define EMEMORY_BASIC(info,data) EMEMORY_BASE(ememory::getLogId(),info,data)
#define EMEMORY_BASIC(info,data) ELOG_BASE(ememory::getLogId(),info,data)
#define EMEMORY_PRINT(data) EMEMORY_BASIC(-1, data)
#define EMEMORY_CRITICAL(data) EMEMORY_BASIC(1, data)

View File

@ -0,0 +1,26 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <ememory/SharedPtr.h>
#include <ememory/WeakPtr.h>
template<typename EMEMORY_TYPE>
ememory::EnableSharedFromThis<EMEMORY_TYPE>::EnableSharedFromThis() :
m_weakThis(static_cast<EMEMORY_TYPE*>(this)) {
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE> ememory::EnableSharedFromThis<EMEMORY_TYPE>::sharedFromThis() {
return m_weakThis.lock();
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE> ememory::EnableSharedFromThis<EMEMORY_TYPE>::weakFromThis() {
return m_weakThis;
}

View File

@ -0,0 +1,193 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <mutex>
#include <ememory/debug.h>
#include <ememory/WeakPtr.h>
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _element):
m_element(_element),
m_counter(nullptr) {
EMEMORY_VERBOSE("new shared");
if (m_element == nullptr) {
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);
if (upperClass != nullptr) {
m_counter = upperClass->m_weakThis;
if (m_counter != nullptr) {
m_counter->incrementShared();
}
} else {
m_counter = new ememory::Counter(false);
}
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(EMEMORY_TYPE* _element):
m_element(_element),
m_counter(nullptr) {
EMEMORY_VERBOSE("new shared");
if (m_element == nullptr) {
return;
}
m_counter = new ememory::Counter(false);
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr():
m_element(nullptr),
m_counter(nullptr) {
EMEMORY_VERBOSE("new shared");
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::~SharedPtr() {
EMEMORY_VERBOSE("delete shared");
reset();
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(const ememory::SharedPtr<EMEMORY_TYPE>& _obj):
m_element(_obj.m_element),
m_counter(_obj.m_counter) {
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>
ememory::SharedPtr<EMEMORY_TYPE>& ememory::SharedPtr<EMEMORY_TYPE>::operator= (const ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
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>
ememory::SharedPtr<EMEMORY_TYPE>::SharedPtr(ememory::SharedPtr<EMEMORY_TYPE>&& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = nullptr;
_obj.m_counter = nullptr;
}
template<typename EMEMORY_TYPE>
void ememory::SharedPtr<EMEMORY_TYPE>::reset() {
if(m_counter == nullptr) {
m_element = nullptr; // in case ...
return;
}
EMEMORY_VERBOSE("reset sharedPtr (start)");
ememory::Counter::remove rmData = m_counter->decrementShared();
switch(rmData) {
case ememory::Counter::remove::all:
delete m_counter;
delete m_element;
break;
case ememory::Counter::remove::data:
delete m_element;
break;
case ememory::Counter::remove::counter:
delete m_counter;
break;
case ememory::Counter::remove::none:
break;
}
m_counter = nullptr;
m_element = nullptr;
EMEMORY_VERBOSE("reset sharedPtr (stop)");
}
template<typename EMEMORY_TYPE>
int64_t ememory::SharedPtr<EMEMORY_TYPE>::useCount() const {
if (m_counter == nullptr) {
return 0;
}
return m_counter->getCountShared();
}
template<typename EMEMORY_TYPE>
bool ememory::SharedPtr<EMEMORY_TYPE>::operator == (std::nullptr_t) {
return m_counter == nullptr;
}
template<typename EMEMORY_TYPE>
bool ememory::SharedPtr<EMEMORY_TYPE>::operator==(const SharedPtr& _obj) const {
return m_counter == _obj.m_counter;
}
template<typename EMEMORY_TYPE>
bool ememory::SharedPtr<EMEMORY_TYPE>::operator != (std::nullptr_t) {
return m_counter != nullptr;
}
template<typename EMEMORY_TYPE>
bool ememory::SharedPtr<EMEMORY_TYPE>::operator!=(const SharedPtr& _obj) const {
return m_counter != _obj.m_counter;
}
template<typename EMEMORY_TYPE>
const EMEMORY_TYPE* ememory::SharedPtr<EMEMORY_TYPE>::get() const {
return m_element;
}
template<typename EMEMORY_TYPE>
EMEMORY_TYPE* ememory::SharedPtr<EMEMORY_TYPE>::get() {
return m_element;
}
template<typename EMEMORY_TYPE>
const EMEMORY_TYPE* ememory::SharedPtr<EMEMORY_TYPE>::operator->() const {
return m_element;
}
template<typename EMEMORY_TYPE>
EMEMORY_TYPE* ememory::SharedPtr<EMEMORY_TYPE>::operator->() {
return m_element;
}
template<typename EMEMORY_TYPE>
const EMEMORY_TYPE& ememory::SharedPtr<EMEMORY_TYPE>::operator*() const {
return *m_element;
}
template<typename EMEMORY_TYPE>
EMEMORY_TYPE& ememory::SharedPtr<EMEMORY_TYPE>::operator*() {
return *m_element;
}
template<typename EMEMORY_TYPE>
void ememory::SharedPtr<EMEMORY_TYPE>::swap(SharedPtr& _obj) {
EMEMORY_TYPE* tmpE = m_element;
ememory::Counter* tmpC = m_counter;
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = tmpE;
_obj.m_counter = tmpC;
}

185
ememory/details/WeakPtr.hxx Normal file
View File

@ -0,0 +1,185 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <mutex>
#include <ememory/debug.h>
#include <ememory/Counter.h>
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr():
m_element(nullptr),
m_counter(nullptr) {
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(EMEMORY_TYPE* _element):
m_element(_element),
m_counter(nullptr) {
EMEMORY_VERBOSE("new weak");
if (m_element == nullptr) {
return;
}
m_counter = new ememory::Counter(true);
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::~WeakPtr() {
reset();
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(const ememory::WeakPtr<EMEMORY_TYPE>& _obj):
m_element(_obj.m_element),
m_counter(_obj.m_counter) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementWeak();
};
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>& ememory::WeakPtr<EMEMORY_TYPE>::operator= (const ememory::WeakPtr<EMEMORY_TYPE>& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
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>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(ememory::WeakPtr<EMEMORY_TYPE>&& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = nullptr;
_obj.m_counter = nullptr;
}
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>::WeakPtr(const ememory::SharedPtr<EMEMORY_TYPE>& _obj):
m_element(_obj.m_element),
m_counter(_obj.m_counter) {
if ( m_element == nullptr
|| m_counter == nullptr) {
m_element = nullptr;
m_counter = nullptr;
return;
}
if (m_counter == nullptr) {
return;
}
m_counter->incrementWeak();
};
template<typename EMEMORY_TYPE>
ememory::WeakPtr<EMEMORY_TYPE>& ememory::WeakPtr<EMEMORY_TYPE>::operator= (const ememory::SharedPtr<EMEMORY_TYPE>& _obj) {
m_element = _obj.m_element;
m_counter = _obj.m_counter;
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) {
m_element = nullptr; // in case ...
return;
}
ememory::Counter::remove rmData = m_counter->decrementWeak();
switch(rmData) {
case ememory::Counter::remove::all:
EMEMORY_ERROR("in WeakPtr request remove all (impossible case ...)");
break;
case ememory::Counter::remove::data:
EMEMORY_ERROR("in WeakPtr request remove all (impossible case ...)");
break;
case ememory::Counter::remove::counter:
delete m_counter;
break;
case ememory::Counter::remove::none:
break;
}
m_counter = nullptr;
m_element = nullptr;
}
template<typename EMEMORY_TYPE>
int ememory::WeakPtr<EMEMORY_TYPE>::useCount() const {
if (m_counter == nullptr) {
return 0;
}
return m_counter->getCountShared();
}
template<typename EMEMORY_TYPE>
bool ememory::WeakPtr<EMEMORY_TYPE>::expired() const {
if (m_counter == nullptr) {
return true;
}
return m_counter->getCountShared() != 0;
}
template<typename EMEMORY_TYPE>
ememory::SharedPtr<EMEMORY_TYPE> ememory::WeakPtr<EMEMORY_TYPE>::lock() {
ememory::SharedPtr<EMEMORY_TYPE> out;
if (m_counter == nullptr) {
return out;
}
int64_t count = m_counter->incrementShared();
if (count == 0) {
return out;
}
out.m_counter = m_counter;
out.m_element = m_element;
return std::move(out);
}
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) {
return m_counter == nullptr;
}
template<typename EMEMORY_TYPE>
void ememory::WeakPtr<EMEMORY_TYPE>::swap(ememory::WeakPtr<EMEMORY_TYPE>& _obj) {
EMEMORY_TYPE* tmpE = m_element;
ememory::Counter* tmpC = m_counter;
m_element = _obj.m_element;
m_counter = _obj.m_counter;
_obj.m_element = tmpE;
_obj.m_counter = tmpC;
}

View File

View File

@ -1,37 +1,19 @@
/**
/** @file
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <vector>
#include <mutex>
#include <memory>
#include <ememory/SharedPtr.h>
#include <ememory/WeakPtr.h>
#include <ememory/EnableSharedFromThis.h>
namespace ememory {
/**
* @brief std::shared_ptr wrapper
*/
template<class TYPE>
using SharedPtr = std::shared_ptr<TYPE>;
/**
* @brief std::weak_ptr wrapper
*/
template<class TYPE>
using WeakPtr = std::weak_ptr<TYPE>;
/**
* @brief std::enable_shared_from_this wrapper
*/
template<class TYPE>
using EnableSharedFromThis = std::enable_shared_from_this<TYPE>;
/*
template<class TYPE>
using DynamicPointerCastZZ = std::dynamic_pointer_cast<TYPE>;
*/
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)...));
}
}

38
lutin_ememory-test.py Normal file
View File

@ -0,0 +1,38 @@
#!/usr/bin/python
import lutin.module as module
import lutin.tools as tools
def get_type():
return "BINARY"
def get_sub_type():
return "TEST"
def get_desc():
return "eSVG test-unit"
def get_licence():
return "APACHE-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([
'test/main.cpp',
'test/testShared.cpp',
'test/testWeak.cpp',
'test/testEnableSharedFromThis.cpp',
'test/testCasts.cpp'
])
my_module.add_module_depend(['ememory', 'gtest', 'test-debug'])
return my_module

View File

@ -29,11 +29,21 @@ def create(target, module_name):
my_module.add_extra_compile_flags()
# add the file to compile:
my_module.add_src_file([
'ememory/debug.cpp'
'ememory/debug.cpp',
'ememory/Counter.cpp'
])
my_module.add_header_file([
'ememory/debug.h',
'ememory/memory.h',
'ememory/Counter.h',
'ememory/SharedPtr.h',
'ememory/WeakPtr.h',
'ememory/EnableSharedFromThis.h',
'ememory/details/memory.hxx',
'ememory/details/SharedPtr.hxx',
'ememory/details/WeakPtr.hxx',
'ememory/details/EnableSharedFromThis.hxx'
])
# build in C++ mode

28
test/main.cpp Normal file
View File

@ -0,0 +1,28 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.h>
#include <vector>
#include <gtest/gtest.h>
#include <etk/etk.h>
int main(int _argc, const char *_argv[]) {
::testing::InitGoogleTest(&_argc, const_cast<char **>(_argv));
etk::init(_argc, _argv);
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if ( data == "-h"
|| data == "--help") {
TEST_PRINT(_argv[0] << " - help : ");
TEST_PRINT(" " << _argv[0] << " [options]");
TEST_PRINT(" No optiions ...");
return -1;
}
}
//etk::initDefaultFolder("esvg-test");
return RUN_ALL_TESTS();
}

6
test/main.h Normal file
View File

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

0
test/testCasts.cpp Normal file
View File

View File

@ -0,0 +1,34 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2014, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <gtest/gtest.h>
#include <ememory/memory.h>
#include "main.h"
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>();
EXPECT_EQ(data.useCount(), 1);
ememory::WeakPtr<testClass> dataWeak = data;
EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(dataWeak.useCount(), 1);
data.reset();
EXPECT_EQ(data.useCount(), 0);
EXPECT_EQ(dataWeak.useCount(), 0);
}

62
test/testShared.cpp Normal file
View File

@ -0,0 +1,62 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2014, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <gtest/gtest.h>
#include <ememory/memory.h>
#include "main.h"
TEST(TestShared, createAndDestroy) {
ememory::SharedPtr<std::string> data = ememory::makeShared<std::string>("coucou");
EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(*data, "coucou");
EXPECT_EQ(data == nullptr, false);
EXPECT_EQ(data != nullptr, true);
data.reset();
EXPECT_EQ(data.useCount(), 0);
EXPECT_EQ(data == nullptr, true);
EXPECT_EQ(data != nullptr, false);
}
TEST(TestShared, copy) {
ememory::SharedPtr<std::string> data = ememory::makeShared<std::string>("coucou");
EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(*data, "coucou");
ememory::SharedPtr<std::string> dataCopy = data;
EXPECT_EQ(data.useCount(), 2);
EXPECT_EQ(data == dataCopy, true);
EXPECT_EQ(data != dataCopy, false);
data.reset();
EXPECT_EQ(data == dataCopy, false);
EXPECT_EQ(data != dataCopy, true);
EXPECT_EQ(data.useCount(), 0);
EXPECT_EQ(dataCopy.useCount(), 1);
EXPECT_EQ(*dataCopy, "coucou");
dataCopy.reset();
EXPECT_EQ(dataCopy.useCount(), 0);
dataCopy.reset();
EXPECT_EQ(dataCopy.useCount(), 0);
}
TEST(TestShared, swap) {
ememory::SharedPtr<std::string> data = ememory::makeShared<std::string>("coucou");
EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(*data, "coucou");
ememory::SharedPtr<std::string> dataCopy;
EXPECT_EQ(dataCopy.useCount(), 0);
dataCopy.swap(data);
EXPECT_EQ(data.useCount(), 0);
EXPECT_EQ(dataCopy.useCount(), 1);
EXPECT_EQ(*dataCopy, "coucou");
}
TEST(TestShared, callOperator) {
ememory::SharedPtr<std::string> data = ememory::makeShared<std::string>("coucou");
EXPECT_EQ(data->size(), 6);
}

47
test/testWeak.cpp Normal file
View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
*
* @copyright 2014, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <gtest/gtest.h>
#include <ememory/memory.h>
#include "main.h"
TEST(TestWeak, createAndDestroy) {
ememory::SharedPtr<std::string> data = ememory::makeShared<std::string>("coucou");
EXPECT_EQ(data.useCount(), 1);
ememory::WeakPtr<std::string> 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(TestWeak, retrive) {
ememory::SharedPtr<std::string> data = ememory::makeShared<std::string>("coucou");
EXPECT_EQ(data.useCount(), 1);
ememory::WeakPtr<std::string> dataWeak = data;
EXPECT_EQ(data.useCount(), 1);
EXPECT_EQ(dataWeak.useCount(), 1);
ememory::SharedPtr<std::string> dataRetrive = dataWeak.lock();
EXPECT_EQ(data.useCount(), 2);
EXPECT_EQ(dataWeak.useCount(), 2);
data.reset();
EXPECT_EQ(data.useCount(), 0);
EXPECT_EQ(dataRetrive.useCount(), 1);
EXPECT_EQ(dataWeak.useCount(), 1);
EXPECT_EQ(*dataRetrive, "coucou");
dataRetrive.reset();
EXPECT_EQ(dataRetrive.useCount(), 0);
EXPECT_EQ(dataWeak.useCount(), 0);
dataRetrive = dataWeak.lock();
EXPECT_EQ(dataRetrive == nullptr, true);
EXPECT_EQ(dataRetrive.useCount(), 0);
EXPECT_EQ(dataWeak.useCount(), 0);
}