summaryrefslogtreecommitdiff
path: root/intellect-framework-from-internet/starts/meaning-vm/level-0/memorystore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intellect-framework-from-internet/starts/meaning-vm/level-0/memorystore.cpp')
-rw-r--r--intellect-framework-from-internet/starts/meaning-vm/level-0/memorystore.cpp179
1 files changed, 179 insertions, 0 deletions
diff --git a/intellect-framework-from-internet/starts/meaning-vm/level-0/memorystore.cpp b/intellect-framework-from-internet/starts/meaning-vm/level-0/memorystore.cpp
new file mode 100644
index 0000000..24e91b0
--- /dev/null
+++ b/intellect-framework-from-internet/starts/meaning-vm/level-0/memorystore.cpp
@@ -0,0 +1,179 @@
+#include "memorystore.hpp"
+#include "concept.hpp"
+#include "errors.hpp"
+#include "ref.hpp"
+
+#include <memory>
+#include <unordered_map>
+
+namespace intellect {
+namespace level0 {
+
+static auto & index()
+{
+ static std::unordered_map<ref, std::unique_ptr<concept>, std::hash<concept*>> index;
+ return index;
+}
+
+
+namespace concepts {
+ ref allocator() { static ref ret = basic_alloc(); return ret; }
+ ref allocates() { static ref ret = basic_alloc(); return ret; }
+ ref allocations() { static ref ret = basic_alloc(); return ret; }
+ ref level0allocations() { static ref ret = basic_alloc(); return ret; }
+}
+
+struct init { init()
+{
+ concepts::allocator().link(concepts::allocator(), concepts::level0allocations());
+ concepts::level0allocations().link(concepts::allocates(), concepts::allocator());
+
+ concepts::allocates().link(concepts::allocator(), concepts::level0allocations());
+ concepts::level0allocations().link(concepts::allocates(), concepts::allocates());
+
+ concepts::allocations().link(concepts::allocator(), concepts::level0allocations());
+ concepts::level0allocations().link(concepts::allocates(), concepts::allocations());
+
+ concepts::level0allocations().link(concepts::allocator(), concepts::level0allocations());
+ concepts::level0allocations().link(concepts::allocates(), concepts::level0allocations());
+} } _init;
+
+ref basic_alloc(std::any data)
+{
+ ref r = new concept();
+ r.ptr()->data = data;
+ index().emplace(r, r.ptr());
+ return r;
+}
+
+ref alloc(ref source, std::any data)
+{
+ ref r = basic_alloc(data);
+ alloc(r, source);
+ return r;
+}
+
+void alloc(ref r, ref source)
+{
+ r.link(concepts::allocator(), source);
+ source.link(concepts::allocates(), r);
+}
+
+void realloc(ref r, ref newsource)
+{
+ ref oldsource = r.get(concepts::allocator());
+ alloc(r, newsource);
+ dealloc(r, oldsource);
+}
+
+static concept* referenced(ref r, concept* source = 0) {
+ for (auto & r2pair : index()) {
+ ref r2 = r2pair.first;
+ if (r2.ptr() == source) {
+ continue;
+ }
+ if (r2 == r) {
+ continue;
+ }
+ for (auto & l : r2.links()) {
+ if (ref(l.first) == r) {
+ return r2;
+ }
+ if (ref(l.second) == r) {
+ return r2;
+ }
+ }
+ }
+ return 0;
+}
+
+void basic_dealloc(ref r)
+{
+ if (r.crucial()) { throw crucial_concept(r); }
+ auto it = index().find(r);
+ if (it == index().end()) { throw no_such_concept(r); }
+
+ concept * referenced = intellect::level0::referenced(r);
+ if (referenced) {
+ throw still_referenced_by(r, referenced);
+ }
+
+ index().erase(it);
+}
+
+void dealloc_from(ref source)
+{
+ std::remove_reference<decltype(index())>::type forgotten;
+
+ auto ours = source.getAll(concepts::allocates());
+ for (auto allocation : ours) {
+ if (allocation.crucial()) { throw crucial_concept(allocation); }
+ source.unlink(concepts::allocates(), allocation);
+ allocation.unlink(concepts::allocator(), source);
+ if (allocation.linked(concepts::allocator())) { continue; }
+
+ auto it = index().find(allocation);
+ if (it != index().end()) {
+ forgotten.insert(index().extract(it));
+ }
+ }
+ try {
+ for (auto allocation : ours ) {
+ for (auto suballocation : allocation.getAll(concepts::allocates())) {
+ // check for this link to find subgroups
+ throw still_referenced_by(allocation, suballocation);
+ }
+ }
+ for (auto ghost : ours) {
+ concept * referenced = intellect::level0::referenced(ghost, source);
+ if (referenced) {
+ throw still_referenced_by(ghost, referenced);
+ }
+ }
+ } catch(...) {
+ // NOTE: this doesn't rebuild deallocated subgroups, but that could be done
+ // by returning them.
+ index().merge(forgotten);
+ for (auto allocation : ours) {
+ source.link(concepts::allocates(), allocation);
+ allocation.link(concepts::allocator(), source);
+ }
+ throw;
+ }
+
+ // concepts in forgotten will be deallocated when they leave scope
+ // note: scoped allocation is just a plan to forget (at the end of a { } block)
+}
+
+void dealloc(ref r, ref source)
+{
+ auto it = index().find(r);
+ if (it == index().end()) { throw no_such_concept(r); }
+
+ source.unlink(concepts::allocates(), r);
+ r.unlink(concepts::allocator(), source);
+ if (r.linked(concepts::allocator())) { return; }
+
+ try {
+ if (r.crucial()) { throw crucial_concept(r); }
+ dealloc_from(r);
+ concept * referenced = intellect::level0::referenced(r, source);
+ if (referenced) {
+ throw still_referenced_by(r, referenced);
+ }
+
+ index().erase(it);
+ } catch(...) {
+ source.link(concepts::allocates(), r);
+ r.link(concepts::allocator(), source);
+ throw;
+ }
+}
+
+std::size_t allocated()
+{
+ return index().size();
+}
+
+}
+}