1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
#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
|