#ifndef SASS_MEMORY_SHARED_PTR_H
|
#define SASS_MEMORY_SHARED_PTR_H
|
|
#include "sass/base.h"
|
|
#include <vector>
|
|
namespace Sass {
|
|
class SharedPtr;
|
|
///////////////////////////////////////////////////////////////////////////////
|
// Use macros for the allocation task, since overloading operator `new`
|
// has been proven to be flaky under certain compilers (see comment below).
|
///////////////////////////////////////////////////////////////////////////////
|
|
#ifdef DEBUG_SHARED_PTR
|
|
#define SASS_MEMORY_NEW(Class, ...) \
|
((Class*)(new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
|
|
#define SASS_MEMORY_COPY(obj) \
|
((obj)->copy(__FILE__, __LINE__)) \
|
|
#define SASS_MEMORY_CLONE(obj) \
|
((obj)->clone(__FILE__, __LINE__)) \
|
|
#else
|
|
#define SASS_MEMORY_NEW(Class, ...) \
|
new Class(__VA_ARGS__) \
|
|
#define SASS_MEMORY_COPY(obj) \
|
((obj)->copy()) \
|
|
#define SASS_MEMORY_CLONE(obj) \
|
((obj)->clone()) \
|
|
#endif
|
|
class SharedObj {
|
protected:
|
friend class SharedPtr;
|
friend class Memory_Manager;
|
#ifdef DEBUG_SHARED_PTR
|
static std::vector<SharedObj*> all;
|
std::string file;
|
size_t line;
|
#endif
|
static bool taint;
|
long refcounter;
|
// long refcount;
|
bool detached;
|
#ifdef DEBUG_SHARED_PTR
|
bool dbg;
|
#endif
|
public:
|
#ifdef DEBUG_SHARED_PTR
|
static void dumpMemLeaks();
|
SharedObj* trace(std::string file, size_t line) {
|
this->file = file;
|
this->line = line;
|
return this;
|
}
|
#endif
|
SharedObj();
|
#ifdef DEBUG_SHARED_PTR
|
std::string getDbgFile() {
|
return file;
|
}
|
size_t getDbgLine() {
|
return line;
|
}
|
void setDbg(bool dbg) {
|
this->dbg = dbg;
|
}
|
#endif
|
static void setTaint(bool val) {
|
taint = val;
|
}
|
virtual ~SharedObj();
|
long getRefCount() {
|
return refcounter;
|
}
|
};
|
|
|
class SharedPtr {
|
protected:
|
SharedObj* node;
|
protected:
|
void decRefCount();
|
void incRefCount();
|
public:
|
// the empty constructor
|
SharedPtr()
|
: node(NULL) {};
|
// the create constructor
|
SharedPtr(SharedObj* ptr);
|
// the copy constructor
|
SharedPtr(const SharedPtr& obj);
|
// the move constructor
|
SharedPtr(SharedPtr&& obj);
|
// copy assignment operator
|
SharedPtr& operator=(const SharedPtr& obj);
|
// move assignment operator
|
SharedPtr& operator=(SharedPtr&& obj);
|
// pure virtual destructor
|
virtual ~SharedPtr() = 0;
|
public:
|
SharedObj* obj () const {
|
return node;
|
};
|
SharedObj* operator-> () const {
|
return node;
|
};
|
bool isNull () {
|
return node == NULL;
|
};
|
bool isNull () const {
|
return node == NULL;
|
};
|
SharedObj* detach() const {
|
if (node) {
|
node->detached = true;
|
}
|
return node;
|
};
|
operator bool() const {
|
return node != NULL;
|
};
|
|
};
|
|
template < class T >
|
class SharedImpl : private SharedPtr {
|
public:
|
SharedImpl()
|
: SharedPtr(NULL) {};
|
SharedImpl(T* node)
|
: SharedPtr(node) {};
|
template < class U >
|
SharedImpl(SharedImpl<U> obj)
|
: SharedPtr(static_cast<T*>(obj.ptr())) {}
|
SharedImpl(T&& node)
|
: SharedPtr(node) {};
|
SharedImpl(const T& node)
|
: SharedPtr(node) {};
|
// the copy constructor
|
SharedImpl(const SharedImpl<T>& impl)
|
: SharedPtr(impl.node) {};
|
// the move constructor
|
SharedImpl(SharedImpl<T>&& impl)
|
: SharedPtr(impl.node) {};
|
// copy assignment operator
|
SharedImpl<T>& operator=(const SharedImpl<T>& rhs) {
|
if (node) decRefCount();
|
node = rhs.node;
|
incRefCount();
|
return *this;
|
}
|
// move assignment operator
|
SharedImpl<T>& operator=(SharedImpl<T>&& rhs) {
|
// don't move our self
|
if (this != &rhs) {
|
if (node) decRefCount();
|
node = std::move(rhs.node);
|
rhs.node = NULL;
|
}
|
return *this;
|
}
|
~SharedImpl() {};
|
public:
|
operator T*() const {
|
return static_cast<T*>(this->obj());
|
}
|
operator T&() const {
|
return *static_cast<T*>(this->obj());
|
}
|
T& operator* () const {
|
return *static_cast<T*>(this->obj());
|
};
|
T* operator-> () const {
|
return static_cast<T*>(this->obj());
|
};
|
T* ptr () const {
|
return static_cast<T*>(this->obj());
|
};
|
T* detach() const {
|
if (this->obj() == NULL) return NULL;
|
return static_cast<T*>(SharedPtr::detach());
|
}
|
bool isNull() const {
|
return this->obj() == NULL;
|
}
|
bool operator<(const T& rhs) const {
|
return *this->ptr() < rhs;
|
};
|
operator bool() const {
|
return this->obj() != NULL;
|
};
|
};
|
|
}
|
|
#endif
|