Added some GC test code. Everything seems to be working.
authorethereal <ethereal@ethv.net>
Wed, 22 Oct 2014 06:06:12 +0000 (23:06 -0700)
committerethereal <ethereal@ethv.net>
Wed, 22 Oct 2014 06:06:12 +0000 (23:06 -0700)
src/main.cpp
src/object/object.hpp
src/object/store.cpp
src/object/store.hpp
src/object/structure.hpp

index bbe804a..cb1f5c8 100644 (file)
@@ -49,6 +49,18 @@ int main(int core_unused argc, const char core_unused *argv[]) {
         as.make_link(o1, o2);
 
         dump_all("During structure", st);
+
+        as.remove_link(o1, o2);
+
+        dump_all("After removal", st);
+
+        st.gc();
+
+        dump_all("After GC", st);
+
+        as.make_link(o2, o1);
+
+        dump_all("After addition", st);
     }
     dump_all("After structure", st);
     st.gc();
index 44415ea..7372e45 100644 (file)
@@ -24,7 +24,6 @@ public:
 private:
     std::unordered_map<std::type_index, boost::any> m_properties;
     std::unordered_map<std::type_index, std::function<void (core::strstream &, boost::any &)>> m_dump_helpers;
-    //std::unordered_map<std::type_index, void (core::strstream &, boost::any &)> m_dump_helpers;
     id_t m_id;
     friend class ref;
     store &m_store;
index f2df29e..3690967 100644 (file)
@@ -32,7 +32,7 @@ void store::gc() {
 
     std::vector<object::id_t> todestroy;
     for(auto it : m_objects) {
-        std::cout << "object " << it.first << " count: " << seen.count(it.first) << std::endl;
+        //std::cout << "object " << it.first << " count: " << seen.count(it.first) << std::endl;
         if(seen.count(it.first)) continue;
         else {
             todestroy.push_back(it.first);
index 0659fd7..cbe6253 100644 (file)
@@ -20,11 +20,11 @@ protected:
     // keep these functions hidden to prevent them from being misused.
     friend class ref;
     void add_ref(object::id_t context, object::id_t target) {
-        std::cout << "adding reference between " << context << " and " << target << std::endl;
+        //std::cout << "adding reference between " << context << " and " << target << " (currently " << m_refs[context][target] << ")" << std::endl;
         m_refs[context][target] ++;
     }
     void remove_ref(object::id_t context, object::id_t target) {
-        std::cout << "removing reference between " << context << " and " << target << std::endl;
+        //std::cout << "removing reference between " << context << " and " << target  << " (currently " << m_refs[context][target] << ")" << std::endl;
         m_refs[context][target] --;
         if(m_refs[context][target] == 0) m_refs[context].erase(target);
         if(m_refs[context].size() == 0) m_refs.erase(context);
index 2501850..6df5350 100644 (file)
@@ -14,23 +14,37 @@ class property;
 
 namespace helpers {
 
-struct per_structure {
-    std::map<object::id_t, ref> links;
+class link_prop : public property {
+private:
+    ref m_ref;
+public:
+    link_prop(ref ref) : m_ref(ref) {}
+
+    const ref &target() const { return m_ref; }
+};
+
+class link_source : public link_prop {
+public:
+    link_source(ref ref) : link_prop(ref) {}
+};
+class link_target : public link_prop {
+public:
+    link_target(ref ref) : link_prop(ref) {}
 };
 
 struct structure_property : public property {
 public:
-    std::map<object::id_t, per_structure> ps;
+    std::map<object::id_t, std::map<object::id_t, ref>> links;
 
     virtual void dump(core::strstream &into) {
         bool first = true;
-        for(auto p : ps) {
+        for(auto p : links) {
             if(!first) into << ", ";
             else first = false;
 
             into << p.first << " -> [";
             bool f2 = true;
-            for(auto l : p.second.links) {
+            for(auto l : p.second) {
                 if(!f2) into << ", ";
                 else f2 = false;
                 into << l.first << ": " << l.second->id();
@@ -48,50 +62,64 @@ private:
     store &m_store;
     ref m_rootobj;
 public:
-    structure(store &store) : m_store(store), m_rootobj(store.make()) {}
+    structure(store &store) : m_store(store), m_rootobj(store.make()) {
+        m_rootobj->set(helpers::structure_property());
+    }
 
     void make_link(const ref &from, const ref &to,
         linkinfo_t &&property = linkinfo_t()) {
         
-        // if it doesn't have a structure property yet, add one.
-        if(!from->has<helpers::structure_property>())
-            from->set(helpers::structure_property());
         // if it doesn't have a link object for this structure, add one.
-        auto &str = from->get<helpers::structure_property>();
-        auto it = str.ps.find(m_rootobj->id());
-        if(it == str.ps.end()) {
-            str.ps.insert(std::make_pair(m_rootobj->id(),
-                helpers::per_structure()));
-            it = str.ps.find(m_rootobj->id());
+        auto &str = m_rootobj->get<helpers::structure_property>();
+        auto it = str.links.find(from->id());
+        if(it == str.links.end()) {
+            str.links.insert(std::make_pair(from->id(),
+                std::map<object::id_t, ref>()));
+            it = str.links.find(from->id());
         }
 
         // create a link object and insert it into the data structures.
         ref link = m_store.make();
         link->set(property);
+        link->set(helpers::link_source(from));
+        link->set(helpers::link_target(to));
         // note that the reference is from the root object.
-        it->second.links.insert(std::make_pair(to->id(), ref(m_rootobj, link)));
+        if(!(it->second.insert(std::make_pair(to->id(),
+            ref(m_rootobj, std::move(link))))).second)
+                throw std::runtime_error("Cannot add already present link");
     }
 
-    /*
-    void make_link(object::id_t from, object::id_t to,
-        linkinfo_t && property = linkinfo_t()) {
-        
-        // if it doesn't have a structure property yet, add one.
-        object &fobj = m_store.get(from);
-        if(!fobj.has<structure_property>()) fobj.set(structure_property());
-        // if it doesn't have a link object for this structure, add one.
-        auto &str = fobj.get<structure_property>();
-        auto it = str.find(m_rootobj);
-        if(it == str.end()) {
-            str.insert(std::make_pair(m_rootobj, std::map<object::id_t, object::id_t>()));
-            it = str.find(m_rootobj);
-        }
+    linkinfo_t *link_raw(const ref &from, const ref &to) {
+        auto &str = m_rootobj->get<helpers::structure_property>();
+        auto it = str.links.find(from->id());
+        if(it == str.links.end()) return nullptr;
+        auto it2 = it->second.find(to->id());
+        if(it2 == it->second.end()) return nullptr;
+        return &it2->second->get<linkinfo_t>();
+    }
 
-        object &lobject = m_store.make();
-        lobject.set(property);
+    bool has_link(const ref &from, const ref &to) {
+        return link_raw(from, to) != nullptr;
+    }
+
+    linkinfo_t &link(const ref &from, const ref &to) {
+        linkinfo_t *raw = link_raw(from, to);
+        if(raw == nullptr) throw std::runtime_error("Need to have linkinfo_t!");
+        return *raw;
+    }
 
-        it->second.insert(std::make_pair(to, lobject.id()));
-    }*/
+    void remove_link(const ref &from, const ref &to) {
+        auto &str = m_rootobj->get<helpers::structure_property>();
+        auto it = str.links.find(from->id());
+        if(it == str.links.end())
+            throw std::runtime_error("Cannot remove nonexistent link");
+        auto it2 = it->second.find(to->id());
+        if(it2 == it->second.end()) 
+            throw std::runtime_error("Cannot remove nonexistent link");
+        it->second.erase(it2);
+
+        if(it->second.size() == 0) str.links.erase(it);
+    }
 };
 
 } // namespace object