Initial work. Replacing with mark/sweep implementation.
authorethereal <ethereal@ethv.net>
Sun, 19 Oct 2014 07:24:18 +0000 (00:24 -0700)
committerethereal <ethereal@ethv.net>
Sun, 19 Oct 2014 07:25:46 +0000 (00:25 -0700)
src/main.cpp
src/object/object.cpp
src/object/object.hpp
src/object/store.hpp [new file with mode: 0644]
src/object/structure.hpp

index 6cd28be..9d24a3c 100644 (file)
@@ -7,6 +7,7 @@
 #include <object/object.hpp>
 #include <object/filter.hpp>
 #include <object/structure.hpp>
+#include <object/store.hpp>
 
 #include <iostream>
 #include <string>
@@ -30,7 +31,8 @@ public:
 };
 
 int main(int core_unused argc, const char core_unused *argv[]) {
-    object::object obj1, obj2;
+    object::store st;
+    object::object obj1 = st.make(), obj2 = st.make();
 
     obj1.set(int_prop());
     obj2.set(str_prop());
@@ -58,5 +60,13 @@ int main(int core_unused argc, const char core_unused *argv[]) {
 
     std::cout << "obj1 -> obj2 link weight: " << wstruct::get_link(obj1, obj2).val << std::endl;
 
+    auto astruct2 = object::structure2<adj_list>();
+
+    astruct2.add_link(obj1, obj2);
+
+    auto astruct3 = object::structure3<adj_list>(st);
+
+    astruct3.make_link(obj1.id(), obj2.id());
+
     return 0;
 }
index a95370d..f2461ae 100644 (file)
@@ -2,6 +2,4 @@
 
 namespace object {
 
-object::id_t object::id_registry::s_lastid = 0;
-
 } // namespace object
index 7a10af1..aaf0ed2 100644 (file)
 
 namespace object {
 
+class store;
+
 class object {
 public:
     using id_t = long;
 private:
-    class id_registry {
-    private:
-        static id_t s_lastid;
-        friend class object;
-
-        static id_t next() { return s_lastid++; }
-    };
-private:
     std::unordered_map<std::type_index, boost::any> m_properties;
     id_t m_id;
-public:
-    object() { m_id = id_registry::next(); }
+    int m_refcount;
+    store &m_store;
+private:
+    friend class store;
+    object(store &store, id_t id) : m_id(id), m_refcount(1), m_store(store) {}
 
+    void inc() { m_refcount ++; }
+    bool dec() { m_refcount --; return m_refcount == 0; }
+public:
     id_t id() const { return m_id; }
 
     template<typename T>
diff --git a/src/object/store.hpp b/src/object/store.hpp
new file mode 100644 (file)
index 0000000..4fc7168
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef OBJECT_STORE_HPP
+#define OBJECT_STORE_HPP
+
+#include <map>
+
+#include "object.hpp"
+
+namespace object {
+
+class store {
+private:
+    std::map<object::id_t, object> m_objects;
+    object::id_t m_lastid;
+protected:
+    friend class object;
+    void destroy(object::id_t id) {
+        if(m_objects.count(id) == 0)
+            throw std::runtime_error("Object does not exist in store");
+        m_objects.erase(m_objects.find(id));
+    }
+public:
+    store() : m_lastid(1) {}
+
+    object &make() {
+        object::id_t id = m_lastid ++;
+        return m_objects.insert(
+            std::make_pair(id, object(*this, id))).first->second;
+    }
+
+    object &get(object::id_t id) {
+        if(m_objects.count(id) == 0)
+            throw std::runtime_error("Object does not exist in store");
+        return m_objects.find(id)->second;
+    }
+
+    const object &get(object::id_t id) const {
+        if(m_objects.count(id) == 0)
+            throw std::runtime_error("Object does not exist in store");
+        return m_objects.find(id)->second;
+    }
+
+    void inc(object::id_t id) {
+        get(id).inc();
+    }
+
+    void dec(object::id_t id) {
+        if(get(id).dec()) destroy(id);
+    }
+};
+
+} // namespace object
+
+#endif
index b7ecaa4..53f92e3 100644 (file)
@@ -5,42 +5,79 @@
 
 #include "object.hpp"
 #include "property.hpp"
+#include "store.hpp"
 
 namespace object {
 
 class property;
 
-template<typename fundamental>
-class structure {
+template<typename link_type>
+class structure2 {
+private:
+    std::map<object::id_t, std::map<object::id_t, link_type>> m_links;
 public:
-    class link_t : property {
-    private:
-        object &m_target;
-        fundamental m_wrapped;
-    private:
-        link_t(object &target, fundamental && towrap) : m_target(target), m_wrapped(towrap) {}
+    void add_link(const object &from, const object &to,
+        link_type &&link = link_type()) {
+
+        add_link(from.id(), to.id(), std::move(link));
+    }
+
+    void add_link(object::id_t from, object::id_t to,
+        link_type &&link = link_type()) {
+        m_links[from][to] = link;
+    }
+    
+    bool has_link(const object &from, const object &to) const
+        { return has_link(from.id(), to.id()); }
+
+    bool has_link(object::id_t from, object::id_t to) const {
+        if(m_links.count(from) == 0) return false;
+        const auto &imap = m_links.find(from)->second;
+        return imap.find(to) != imap.end();
+    }
+
+    link_type &link(object &from, object &to) {
+        if(!has_link(from.id(), to.id()))
+            throw std::runtime_error("No structural link between requested objects");
 
+        return m_links[from][to];
+    }
+
+    const link_type &link(object &from, object &to) const {
+        if(!has_link(from.id(), to.id()))
+            throw std::runtime_error("No structural link between requested objects");
+        
+        return m_links.find(from)->second.find(to)->second;
+    }
+
+    void remove_link(object &from, object &to) {
+        if(!has_link(from.id(), to.id()))
+            throw std::runtime_error("Cannot remove nonexistent edge.");
+    }
+};
+
+template<typename fundamental>
+class structure {
+private:
+    class link_t {
+        object &obj;
+        fundamental property;
+        link_t(object &obj, fundamental && property) : obj(obj), property(std::move(property)) {}
         friend class structure<fundamental>;
     };
     class adj_t : property {
-    private:
-        std::map<object::id_t, object> m_links;
+        std::map<object::id_t, link_t> m_links;
         friend class structure<fundamental>;
     };
-private:
-    
 public:
     static bool make_link(object &from, object &target, fundamental && property = fundamental()) {
-        object link;
         if(!from.has<adj_t>()) from.set(adj_t());
         auto &links = from.get<adj_t>().m_links;
         // already present?
         auto it = links.find(target.id());
         if(it != links.end()) return false;
 
-        link.set(link_t(target, std::move(property)));
-        
-        links.insert(std::make_pair(target.id(), std::move(link)));
+        links.insert(std::make_pair(target.id(), link_t(target, std::move(property))));
 
         return true;
     }
@@ -55,7 +92,60 @@ public:
         auto it = links.find(target.id());
         if(it == links.end()) throw std::runtime_error("no such link");
 
-        return (it->second).template get<link_t>().m_wrapped;
+        return it->second.property;
+    }
+};
+
+// object.structure_property[structure ID][destination ID] = edge object ID
+class structure_property : property,
+    public std::map<object::id_t, std::map<object::id_t, object::id_t>> {};
+
+template<typename linkinfo_t>
+class structure3 {
+private:
+    class link_t : public property {
+    public:
+        
+    };
+private:
+    store &m_store;
+    object::id_t m_rootobj;
+public:
+    structure3(store &store) : m_store(store) {
+        m_rootobj = store.make().id();
+    }
+
+    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);
+        }
+
+        object &lobject = m_store.make();
+        lobject.set(property);
+
+        it->second.insert(std::make_pair(to, lobject.id()));
+    }
+
+    linkinfo_t &get_link(object::id_t from, object::id_t to) {
+        // 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);
+        }
     }
 };