use custom shared pointer

- simplify memory management
This commit is contained in:
Hannes Janetzek 2016-11-18 22:46:46 +01:00
parent c8b1e9d7c5
commit 7a52c16563
11 changed files with 178 additions and 53 deletions

View File

@ -15,7 +15,6 @@
namespace YAML { namespace YAML {
namespace detail { namespace detail {
struct iterator_value;
template <typename V> template <typename V>
class iterator_base : public std::iterator<std::forward_iterator_tag, V, class iterator_base : public std::iterator<std::forward_iterator_tag, V,
@ -39,7 +38,7 @@ class iterator_base : public std::iterator<std::forward_iterator_tag, V,
typedef typename iterator_base::value_type value_type; typedef typename iterator_base::value_type value_type;
public: public:
iterator_base() : m_iterator(), m_pMemory() {} iterator_base() : m_iterator(), m_pMemory(nullptr) {}
explicit iterator_base(base_type rhs, shared_memory_holder pMemory) explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
: m_iterator(rhs), m_pMemory(pMemory) {} : m_iterator(rhs), m_pMemory(pMemory) {}

View File

@ -7,7 +7,7 @@
#pragma once #pragma once
#endif #endif
#include <set> #include <list>
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/ptr.h"
@ -15,31 +15,43 @@
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class node; class node;
} // namespace detail } // namespace detail
} // namespace YAML } // namespace YAML
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class YAML_CPP_API memory {
class YAML_CPP_API memory : public ref_counted {
public: public:
node& create_node(); node& create_node();
void merge(const memory& rhs); void merge(memory&& rhs);
memory();
~memory();
private: private:
typedef std::set<shared_node> Nodes; typedef std::list<node> Nodes;
Nodes m_nodes; Nodes m_nodes;
}; };
class YAML_CPP_API memory_holder { typedef ref_holder<memory> shared_memory;
class YAML_CPP_API memory_holder : public ref_counted {
public: public:
memory_holder() : m_pMemory(new memory) {} memory_holder();
~memory_holder();
node& create_node() { return m_pMemory->create_node(); } node& create_node() { return m_pMemory->create_node(); }
void merge(memory_holder& rhs); void merge(memory_holder& rhs);
private: private:
shared_memory m_pMemory; shared_memory m_pMemory;
}; };
typedef ref_holder<memory_holder> shared_memory_holder;
} }
} }

View File

@ -12,13 +12,19 @@
#include "yaml-cpp/node/type.h" #include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_data.h" #include "yaml-cpp/node/detail/node_data.h"
#include "yaml-cpp/node/detail/memory.h"
#include <set> #include <set>
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class node { class node {
using node_data_ref = ref_holder<node_data>;
public: public:
node() : m_pRef(new node_data) {}
node() : m_pRef(new node_data){}
node(const node&) = delete; node(const node&) = delete;
node& operator=(const node&) = delete; node& operator=(const node&) = delete;
@ -37,24 +43,6 @@ class node {
bool equals(const T& rhs, shared_memory_holder pMemory); bool equals(const T& rhs, shared_memory_holder pMemory);
bool equals(const char* rhs, shared_memory_holder pMemory); bool equals(const char* rhs, shared_memory_holder pMemory);
void mark_defined() {
if (is_defined())
return;
m_pRef->mark_defined();
for (nodes::iterator it = m_dependencies.begin();
it != m_dependencies.end(); ++it)
(*it)->mark_defined();
m_dependencies.clear();
}
void add_dependency(node& rhs) {
if (is_defined())
rhs.mark_defined();
else
m_dependencies.insert(&rhs);
}
void set_ref(const node& rhs) { void set_ref(const node& rhs) {
if (rhs.is_defined()) if (rhs.is_defined())
mark_defined(); mark_defined();
@ -159,7 +147,25 @@ class node {
} }
private: private:
shared_node_data m_pRef; void mark_defined() {
if (is_defined())
return;
m_pRef->mark_defined();
for (nodes::iterator it = m_dependencies.begin();
it != m_dependencies.end(); ++it)
(*it)->mark_defined();
m_dependencies.clear();
}
void add_dependency(node& rhs) {
if (is_defined())
rhs.mark_defined();
else
m_dependencies.insert(&rhs);
}
mutable node_data_ref m_pRef;
typedef std::set<node*> nodes; typedef std::set<node*> nodes;
nodes m_dependencies; nodes m_dependencies;
}; };

View File

@ -27,7 +27,7 @@ class node;
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class YAML_CPP_API node_data { class YAML_CPP_API node_data : public ref_counted {
public: public:
node_data(); node_data();
node_data(const node_data&) = delete; node_data(const node_data&) = delete;
@ -121,6 +121,7 @@ class YAML_CPP_API node_data {
typedef std::pair<node*, node*> kv_pair; typedef std::pair<node*, node*> kv_pair;
typedef std::list<kv_pair> kv_pairs; typedef std::list<kv_pair> kv_pairs;
mutable kv_pairs m_undefinedPairs; mutable kv_pairs m_undefinedPairs;
}; };
} }
} }

View File

@ -15,12 +15,16 @@
#include <string> #include <string>
namespace YAML { namespace YAML {
inline Node::Node() : m_isValid(true), m_pNode(NULL) {} inline Node::Node()
: m_isValid(true),
//m_pMemory(nullptr),
m_pMemory(new detail::memory_holder),
m_pNode(NULL) {}
inline Node::Node(NodeType::value type) inline Node::Node(NodeType::value type)
: m_isValid(true), : m_isValid(true),
m_pMemory(new detail::memory_holder), m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) { m_pNode(&(m_pMemory->create_node())) {
m_pNode->set_type(type); m_pNode->set_type(type);
} }
@ -28,7 +32,7 @@ template <typename T>
inline Node::Node(const T& rhs) inline Node::Node(const T& rhs)
: m_isValid(true), : m_isValid(true),
m_pMemory(new detail::memory_holder), m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) { m_pNode(&(m_pMemory->create_node())) {
Assign(rhs); Assign(rhs);
} }
@ -42,10 +46,15 @@ inline Node::Node(const Node& rhs)
m_pMemory(rhs.m_pMemory), m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {} m_pNode(rhs.m_pNode) {}
inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {} inline Node::Node(Zombie)
: m_isValid(false),
m_pMemory(nullptr),
m_pNode(NULL) {}
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory) inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {} : m_isValid(true),
m_pMemory(pMemory),
m_pNode(&node) {}
inline Node::~Node() {} inline Node::~Node() {}

View File

@ -24,6 +24,12 @@ struct iterator_value : public Node, std::pair<Node, Node> {
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
explicit iterator_value(const Node& key, const Node& value) explicit iterator_value(const Node& key, const Node& value)
: Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {} : Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
explicit iterator_value(Node&& rhs)
: Node(std::move(rhs)),
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
explicit iterator_value(Node&& key, Node&& value)
: Node(Node::ZombieNode), std::pair<Node, Node>(std::move(key), std::move(value)) {}
}; };
} }
} }

View File

@ -14,7 +14,7 @@
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/bool_type.h" #include "yaml-cpp/node/detail/bool_type.h"
#include "yaml-cpp/node/detail/iterator_fwd.h" #include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/type.h" #include "yaml-cpp/node/type.h"
namespace YAML { namespace YAML {

View File

@ -8,19 +8,105 @@
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include <memory>
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class node;
class node_data;
class memory;
class memory_holder;
typedef std::shared_ptr<node> shared_node; template <typename T>
typedef std::shared_ptr<node_data> shared_node_data; struct ref_holder {
typedef std::shared_ptr<memory_holder> shared_memory_holder; ~ref_holder<T>() {
typedef std::shared_ptr<memory> shared_memory; if (m_ptr)
m_ptr->release();
}
ref_holder<T>(T* ptr) {
if (ptr) {
ptr->hold();
}
m_ptr = ptr;
}
ref_holder<T>(const ref_holder<T>& ref) {
if (ref.m_ptr) {
ref.m_ptr->hold();
}
m_ptr = ref.m_ptr;
}
ref_holder<T>(ref_holder<T>&& ref) {
m_ptr = ref.m_ptr;
ref.m_ptr = nullptr;
}
ref_holder<T>& operator=(const ref_holder<T>& ref) {
if (ref.m_ptr == m_ptr) {
return *this;
}
if (ref.m_ptr) {
ref.m_ptr->hold();
}
if (m_ptr) {
m_ptr->release();
}
m_ptr = ref.m_ptr;
return *this;
}
ref_holder<T>& operator=(ref_holder<T>&& ref) {
if (ref.m_ptr == m_ptr) {
return *this;
}
if (m_ptr) {
m_ptr->release();
}
m_ptr = ref.m_ptr;
ref.m_ptr = nullptr;
return *this;
}
bool operator==(const ref_holder<T>& ref) const { return m_ptr == ref.m_ptr; }
bool operator!=(const ref_holder<T>& ref) const { return m_ptr != ref.m_ptr; }
const T* operator->() const { return m_ptr; }
T* operator->() { return m_ptr; }
const T& operator*() const { return *m_ptr; }
T& operator*() { return *m_ptr; }
const T* get() { return m_ptr; }
void reset(T* ptr) {
if (ptr == m_ptr) {
return;
}
if (m_ptr) {
m_ptr->release();
}
if (ptr) {
ptr->hold();
}
m_ptr = ptr;
}
operator bool() const { return m_ptr != nullptr; }
private:
T* m_ptr;
};
struct ref_counted {
void hold() { m_refs++; }
void release() {
if (--m_refs == 0) {
delete this;
}
}
virtual ~ref_counted() {}
private:
std::size_t m_refs = 0;
};
} }
} }

View File

@ -5,22 +5,27 @@
namespace YAML { namespace YAML {
namespace detail { namespace detail {
typedef ref_holder<node> node_ref;
void memory_holder::merge(memory_holder& rhs) { void memory_holder::merge(memory_holder& rhs) {
if (m_pMemory == rhs.m_pMemory) if (m_pMemory == rhs.m_pMemory)
return; return;
m_pMemory->merge(*rhs.m_pMemory); m_pMemory->merge(std::move(*rhs.m_pMemory));
rhs.m_pMemory = m_pMemory; rhs.m_pMemory = m_pMemory;
} }
node& memory::create_node() { node& memory::create_node() {
shared_node pNode(new node); m_nodes.emplace_back();
m_nodes.insert(pNode); return m_nodes.back();
return *pNode;
} }
void memory::merge(const memory& rhs) { void memory::merge(memory&& rhs) { m_nodes.splice(m_nodes.end(), rhs.m_nodes); }
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
} memory_holder::memory_holder() : m_pMemory(new memory) {}
memory_holder::~memory_holder() {}
memory::memory() {}
memory::~memory() {}
} }
} }

View File

@ -12,7 +12,7 @@
#include "yaml-cpp/anchor.h" #include "yaml-cpp/anchor.h"
#include "yaml-cpp/emitterstyle.h" #include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/detail/memory.h"
namespace YAML { namespace YAML {
namespace detail { namespace detail {

View File

@ -11,11 +11,12 @@
#include <vector> #include <vector>
#include "yaml-cpp/anchor.h" #include "yaml-cpp/anchor.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/detail/memory.h"
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class node; class node;
class node_data;
} // namespace detail } // namespace detail
} // namespace YAML } // namespace YAML