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 detail {
struct iterator_value;
template <typename 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;
public:
iterator_base() : m_iterator(), m_pMemory() {}
iterator_base() : m_iterator(), m_pMemory(nullptr) {}
explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
: m_iterator(rhs), m_pMemory(pMemory) {}

View File

@ -7,7 +7,7 @@
#pragma once
#endif
#include <set>
#include <list>
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
@ -15,31 +15,43 @@
namespace YAML {
namespace detail {
class node;
} // namespace detail
} // namespace YAML
namespace YAML {
namespace detail {
class YAML_CPP_API memory {
class YAML_CPP_API memory : public ref_counted {
public:
node& create_node();
void merge(const memory& rhs);
void merge(memory&& rhs);
memory();
~memory();
private:
typedef std::set<shared_node> Nodes;
typedef std::list<node> 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:
memory_holder() : m_pMemory(new memory) {}
memory_holder();
~memory_holder();
node& create_node() { return m_pMemory->create_node(); }
void merge(memory_holder& rhs);
private:
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/ptr.h"
#include "yaml-cpp/node/detail/node_data.h"
#include "yaml-cpp/node/detail/memory.h"
#include <set>
namespace YAML {
namespace detail {
class node {
using node_data_ref = ref_holder<node_data>;
public:
node() : m_pRef(new node_data) {}
node() : m_pRef(new node_data){}
node(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 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) {
if (rhs.is_defined())
mark_defined();
@ -159,7 +147,25 @@ class node {
}
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;
nodes m_dependencies;
};

View File

@ -27,7 +27,7 @@ class node;
namespace YAML {
namespace detail {
class YAML_CPP_API node_data {
class YAML_CPP_API node_data : public ref_counted {
public:
node_data();
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::list<kv_pair> kv_pairs;
mutable kv_pairs m_undefinedPairs;
};
}
}

View File

@ -15,12 +15,16 @@
#include <string>
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)
: m_isValid(true),
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
m_pNode(&(m_pMemory->create_node())) {
m_pNode->set_type(type);
}
@ -28,7 +32,7 @@ template <typename T>
inline Node::Node(const T& rhs)
: m_isValid(true),
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
m_pNode(&(m_pMemory->create_node())) {
Assign(rhs);
}
@ -42,10 +46,15 @@ inline Node::Node(const Node& rhs)
m_pMemory(rhs.m_pMemory),
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)
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
: m_isValid(true),
m_pMemory(pMemory),
m_pNode(&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)) {}
explicit iterator_value(const Node& key, const Node& 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/node/detail/bool_type.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"
namespace YAML {

View File

@ -8,19 +8,105 @@
#endif
#include "yaml-cpp/dll.h"
#include <memory>
namespace YAML {
namespace detail {
class node;
class node_data;
class memory;
class memory_holder;
typedef std::shared_ptr<node> shared_node;
typedef std::shared_ptr<node_data> shared_node_data;
typedef std::shared_ptr<memory_holder> shared_memory_holder;
typedef std::shared_ptr<memory> shared_memory;
template <typename T>
struct ref_holder {
~ref_holder<T>() {
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 detail {
typedef ref_holder<node> node_ref;
void memory_holder::merge(memory_holder& rhs) {
if (m_pMemory == rhs.m_pMemory)
return;
m_pMemory->merge(*rhs.m_pMemory);
m_pMemory->merge(std::move(*rhs.m_pMemory));
rhs.m_pMemory = m_pMemory;
}
node& memory::create_node() {
shared_node pNode(new node);
m_nodes.insert(pNode);
return *pNode;
m_nodes.emplace_back();
return m_nodes.back();
}
void memory::merge(const memory& rhs) {
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
}
void memory::merge(memory&& rhs) { m_nodes.splice(m_nodes.end(), rhs.m_nodes); }
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/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/memory.h"
namespace YAML {
namespace detail {

View File

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