diff --git a/include/yaml-cpp/node/detail/iterator.h b/include/yaml-cpp/node/detail/iterator.h index cc5f9d3..82b00df 100644 --- a/include/yaml-cpp/node/detail/iterator.h +++ b/include/yaml-cpp/node/detail/iterator.h @@ -15,7 +15,6 @@ namespace YAML { namespace detail { -struct iterator_value; template class iterator_base : public std::iterator +#include #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 Nodes; + typedef std::list Nodes; Nodes m_nodes; }; -class YAML_CPP_API memory_holder { +typedef ref_holder 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 shared_memory_holder; + } } diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index 77d1859..5cdea90 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -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 namespace YAML { namespace detail { class node { + + using node_data_ref = ref_holder; + 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 nodes; nodes m_dependencies; }; diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 01cf7d4..33a2979 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -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 kv_pair; typedef std::list kv_pairs; mutable kv_pairs m_undefinedPairs; + }; } } diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 68cc582..c302608 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -15,12 +15,16 @@ #include 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 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() {} diff --git a/include/yaml-cpp/node/iterator.h b/include/yaml-cpp/node/iterator.h index 366a9c8..26f6055 100644 --- a/include/yaml-cpp/node/iterator.h +++ b/include/yaml-cpp/node/iterator.h @@ -24,6 +24,12 @@ struct iterator_value : public Node, std::pair { std::pair(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} explicit iterator_value(const Node& key, const Node& value) : Node(Node::ZombieNode), std::pair(key, value) {} + + explicit iterator_value(Node&& rhs) + : Node(std::move(rhs)), + std::pair(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} + explicit iterator_value(Node&& key, Node&& value) + : Node(Node::ZombieNode), std::pair(std::move(key), std::move(value)) {} }; } } diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 4e515d2..768e0c8 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -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 { diff --git a/include/yaml-cpp/node/ptr.h b/include/yaml-cpp/node/ptr.h index 6ac80ac..30aae81 100644 --- a/include/yaml-cpp/node/ptr.h +++ b/include/yaml-cpp/node/ptr.h @@ -8,19 +8,105 @@ #endif #include "yaml-cpp/dll.h" -#include namespace YAML { namespace detail { -class node; -class node_data; -class memory; -class memory_holder; -typedef std::shared_ptr shared_node; -typedef std::shared_ptr shared_node_data; -typedef std::shared_ptr shared_memory_holder; -typedef std::shared_ptr shared_memory; +template +struct ref_holder { + ~ref_holder() { + if (m_ptr) + m_ptr->release(); + } + ref_holder(T* ptr) { + if (ptr) { + ptr->hold(); + } + m_ptr = ptr; + } + + ref_holder(const ref_holder& ref) { + if (ref.m_ptr) { + ref.m_ptr->hold(); + } + m_ptr = ref.m_ptr; + } + + ref_holder(ref_holder&& ref) { + m_ptr = ref.m_ptr; + ref.m_ptr = nullptr; + } + + ref_holder& operator=(const ref_holder& 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& operator=(ref_holder&& 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& ref) const { return m_ptr == ref.m_ptr; } + bool operator!=(const ref_holder& 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; +}; } } diff --git a/src/memory.cpp b/src/memory.cpp index e5f8a9d..59c87aa 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -5,22 +5,27 @@ namespace YAML { namespace detail { +typedef ref_holder 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() {} } } diff --git a/src/nodebuilder.h b/src/nodebuilder.h index a6a47f0..e0eb0b8 100644 --- a/src/nodebuilder.h +++ b/src/nodebuilder.h @@ -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 { diff --git a/src/nodeevents.h b/src/nodeevents.h index 6c26b96..2bd5af0 100644 --- a/src/nodeevents.h +++ b/src/nodeevents.h @@ -11,11 +11,12 @@ #include #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