From 1b8c47a8b14f784f6605eee3a73713dbce6ca572 Mon Sep 17 00:00:00 2001 From: olpc user Date: Mon, 9 Dec 2019 20:38:22 -0800 Subject: changed level-0 allocation to use groups --- starts/meaning-vm/level-0/baseref.hpp | 4 +- starts/meaning-vm/level-0/concept.cpp | 1 + starts/meaning-vm/level-0/memorystore.cpp | 94 +++++++++++++++++++++++-------- starts/meaning-vm/level-0/memorystore.hpp | 37 +++++++++++- starts/meaning-vm/level-0/ref.cpp | 4 ++ 5 files changed, 114 insertions(+), 26 deletions(-) (limited to 'starts/meaning-vm/level-0') diff --git a/starts/meaning-vm/level-0/baseref.hpp b/starts/meaning-vm/level-0/baseref.hpp index fbb7a28..69880c8 100644 --- a/starts/meaning-vm/level-0/baseref.hpp +++ b/starts/meaning-vm/level-0/baseref.hpp @@ -57,7 +57,7 @@ public: template T& vget(ref const & type) const { return p->vget(type.p); } template - void vset(ref const & type, T const & v) { p->set(type.p, level0::alloc(v)); } + void vset(ref const & type, T const & v) { p->set(type.p, level0::alloc(self, v)); } template T& val() { return p->val(); } @@ -100,7 +100,7 @@ private: bool operator!=(mutit const & other) const { return self.it != other.it; } val & operator*() { return *(val*)&self.it.operator*(); } - val & operator->() { return *(val*)&self.it.operator->(); } + val * operator->() { return (val*)self.it.operator->(); } private: It it; diff --git a/starts/meaning-vm/level-0/concept.cpp b/starts/meaning-vm/level-0/concept.cpp index 9bb772d..0661edd 100644 --- a/starts/meaning-vm/level-0/concept.cpp +++ b/starts/meaning-vm/level-0/concept.cpp @@ -12,6 +12,7 @@ concept* concept::id() void concept::link(concept* type, concept* target) { + if (type == 0 || target == 0) { throw null_reference(); } links.insert({type, target}); } diff --git a/starts/meaning-vm/level-0/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp index adae8b2..61f8ec0 100644 --- a/starts/meaning-vm/level-0/memorystore.cpp +++ b/starts/meaning-vm/level-0/memorystore.cpp @@ -8,21 +8,66 @@ namespace intellect { namespace level0 { -static auto & concepts() +static auto & index() { - static std::unordered_set> concepts; - return concepts; + static std::unordered_set> index; + return index; } -ref alloc(std::any data) { + +namespace concepts { + ref allocator() { static ref ret = new concept(); return ret; }; + ref allocates() { static ref ret = new concept(); return ret; }; + ref allocations() { static ref ret = new concept(); return ret; }; + ref level0allocations() { static ref ret = new concept(); return ret; }; +} + +struct init { init() +{ + concepts::allocator().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::allocator()); + index().insert(concepts::allocator()); + + concepts::allocates().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::allocates()); + index().insert(concepts::allocates()); + + concepts::allocations().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::allocations()); + index().insert(concepts::allocations()); + + concepts::level0allocations().link(concepts::allocator(), concepts::level0allocations()); + concepts::level0allocations().link(concepts::allocates(), concepts::level0allocations()); + index().insert(concepts::level0allocations()); +} } _init; + +ref alloc(ref source, std::any data) +{ concept * r = new concept(); r->data = data; - concepts().insert(r); + alloc((ref)r, source); + index().insert(r); return r; } -static concept* referenced(ref r) { - for (ref r2 : concepts()) { +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, ref source) { + for (ref r2 : index()) { + if (r2 == source) { + continue; + } if (r2 == r) { continue; } @@ -38,28 +83,33 @@ static concept* referenced(ref r) { return 0; } -void dealloc(ref r) { - concept * referenced = intellect::level0::referenced(r); - if (referenced) { - throw still_referenced_by(r, referenced); +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; } + + index().erase(it); + + auto ours = r.getAll(concepts::allocates()); + for (auto allocation : ours) { + dealloc(allocation, r); } - for ( - auto it = concepts().begin(); - it != concepts().end(); - ++ it) - { - if (*it == r) { - concepts().erase(it); - delete (concept*)r; - return; + + for (auto ghost : ours) { + concept * referenced = intellect::level0::referenced(ghost, source); + if (referenced) { + throw still_referenced_by(ghost, referenced); } } - throw no_such_concept(r); + delete (concept*)r; } std::size_t allocated() { - return concepts().size(); + return index().size(); } } diff --git a/starts/meaning-vm/level-0/memorystore.hpp b/starts/meaning-vm/level-0/memorystore.hpp index 7843513..eff4235 100644 --- a/starts/meaning-vm/level-0/memorystore.hpp +++ b/starts/meaning-vm/level-0/memorystore.hpp @@ -7,8 +7,41 @@ namespace intellect { namespace level0 { -ref alloc(std::any data = {}); -void dealloc(ref); +// self-reference loops are real. +// +// one person can feel urgent about issue A, and act on this urgency to engage +// another person around B, who acts in a different way to someone else, eventually +// cycling back to stress that stimulates the original person to feel more urgent +// about issue A. +// human behavior can make arbitrary positive or negative feedback loops. +// +// here in memory allocation, i've designed a system intended to reduce such loops +// by encouraging my usage to be a certain way, but it still readily provides for +// them. +// +// in process expansion / simple thought, we also have the issue of recursion. +// if we trust a task to complete, and it ends up triggering itself in a subcontext, +// we could wait forever. +// +// the solution to many of these things is to recognize repetition in systems. +// we also become skeptical as things continue constantly. we expect to develop +// some level of understanding that they will shrink, or we stop them and try +// something else. + +namespace concepts { + +extern ref allocator(); // link shows what is holding something alive +extern ref allocates(); // link shows what is being held alive + +extern ref allocations(); // to use as a basic allocator for simple things +extern ref level0allocations(); // allocator for concepts internal to level0 + +} + +ref alloc(ref allocator, std::any data = {}); // new concept +void alloc(ref allocated, ref allocator); // extra ownership for concept +void realloc(ref allocated, ref allocator); // move ownership for concept to allocator +void dealloc(ref allocated, ref allocator); // remove ownership for concept std::size_t allocated(); } diff --git a/starts/meaning-vm/level-0/ref.cpp b/starts/meaning-vm/level-0/ref.cpp index d4758bd..87e911a 100644 --- a/starts/meaning-vm/level-0/ref.cpp +++ b/starts/meaning-vm/level-0/ref.cpp @@ -1,10 +1,12 @@ #include "ref.hpp" #include "concept.hpp" #include "errors.hpp" +#include "memorystore.hpp" #include using namespace intellect::level0; +using namespace concepts; std::string ref::dump(ref skipmarkertype, ref skipmarkertarget) { @@ -13,10 +15,12 @@ std::string ref::dump(ref skipmarkertype, ref skipmarkertarget) } std::string ret = std::to_string((unsigned long)ptr()) + ":\n"; for (auto & link : self.links()) { + if (link.first.linked(allocator(), level0allocations())) { continue; } ret += " " + std::to_string((unsigned long)link.first.ptr()) + ": " + std::to_string((unsigned long)link.second.ptr()) + "\n"; } self.link(skipmarkertype, skipmarkertarget); for (auto & link : self.links()) { + if (link.first.linked(allocator(), level0allocations())) { continue; } if (link.first == skipmarkertype && link.second == skipmarkertarget) { continue; } -- cgit v1.2.3 From d84b81bc12e6a22e442d5dce38e59222119311f0 Mon Sep 17 00:00:00 2001 From: olpc user Date: Tue, 10 Dec 2019 06:55:35 -0800 Subject: readded basic allocation; held pointers with a std::unique_ptr; added some words around increasing relevence --- starts/meaning-vm/level-0/memorystore.cpp | 112 +++++++++++++++++++++++------- starts/meaning-vm/level-0/memorystore.hpp | 4 ++ starts/meaning-vm/level0.cpp | 2 + starts/meaning-vm/level1.cpp | 2 +- starts/meaning-vm/makefile | 2 +- 5 files changed, 93 insertions(+), 29 deletions(-) (limited to 'starts/meaning-vm/level-0') diff --git a/starts/meaning-vm/level-0/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp index 61f8ec0..220d0c3 100644 --- a/starts/meaning-vm/level-0/memorystore.cpp +++ b/starts/meaning-vm/level-0/memorystore.cpp @@ -3,50 +3,53 @@ #include "errors.hpp" #include "ref.hpp" -#include +#include +#include namespace intellect { namespace level0 { static auto & index() { - static std::unordered_set> index; + static std::unordered_map, std::hash> index; return index; } namespace concepts { - ref allocator() { static ref ret = new concept(); return ret; }; - ref allocates() { static ref ret = new concept(); return ret; }; - ref allocations() { static ref ret = new concept(); return ret; }; - ref level0allocations() { static ref ret = new concept(); return ret; }; + 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()); - index().insert(concepts::allocator()); concepts::allocates().link(concepts::allocator(), concepts::level0allocations()); concepts::level0allocations().link(concepts::allocates(), concepts::allocates()); - index().insert(concepts::allocates()); concepts::allocations().link(concepts::allocator(), concepts::level0allocations()); concepts::level0allocations().link(concepts::allocates(), concepts::allocations()); - index().insert(concepts::allocations()); concepts::level0allocations().link(concepts::allocator(), concepts::level0allocations()); concepts::level0allocations().link(concepts::allocates(), concepts::level0allocations()); - index().insert(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) { - concept * r = new concept(); - r->data = data; - alloc((ref)r, source); - index().insert(r); + ref r = basic_alloc(data); + alloc(r, source); return r; } @@ -63,9 +66,10 @@ void realloc(ref r, ref newsource) dealloc(r, oldsource); } -static concept* referenced(ref r, ref source) { - for (ref r2 : index()) { - if (r2 == source) { +static concept* referenced(ref r, concept* source = 0) { + for (auto & r2pair : index()) { + ref r2 = r2pair.first; + if (r2.ptr() == source) { continue; } if (r2 == r) { @@ -83,28 +87,82 @@ static concept* referenced(ref r, ref source) { return 0; } -void dealloc(ref r, ref source) { +void basic_dealloc(ref r) +{ 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; } + 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::type forgotten; - auto ours = r.getAll(concepts::allocates()); + auto ours = source.getAll(concepts::allocates()); for (auto allocation : ours) { - dealloc(allocation, r); + 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 ) { + if (allocation.linked(concepts::allocates())) { + dealloc_from(allocation); + } + } + 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; } - for (auto ghost : ours) { - concept * referenced = intellect::level0::referenced(ghost, source); + // 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 { + dealloc_from(r); + concept * referenced = intellect::level0::referenced(r, source); if (referenced) { - throw still_referenced_by(ghost, referenced); + throw still_referenced_by(r, referenced); } + + index().erase(it); + } catch(...) { + source.link(concepts::allocates(), r); + r.link(concepts::allocator(), source); } - delete (concept*)r; } std::size_t allocated() diff --git a/starts/meaning-vm/level-0/memorystore.hpp b/starts/meaning-vm/level-0/memorystore.hpp index eff4235..f4faa13 100644 --- a/starts/meaning-vm/level-0/memorystore.hpp +++ b/starts/meaning-vm/level-0/memorystore.hpp @@ -38,9 +38,13 @@ extern ref level0allocations(); // allocator for concepts internal to level0 } +ref basic_alloc(std::any data = {}); +void basic_dealloc(ref allocated); + ref alloc(ref allocator, std::any data = {}); // new concept void alloc(ref allocated, ref allocator); // extra ownership for concept void realloc(ref allocated, ref allocator); // move ownership for concept to allocator +[[deprecated("can make recursion: turn to workable habits")]] void dealloc(ref allocated, ref allocator); // remove ownership for concept std::size_t allocated(); diff --git a/starts/meaning-vm/level0.cpp b/starts/meaning-vm/level0.cpp index 86ce0cd..4ab8b7b 100644 --- a/starts/meaning-vm/level0.cpp +++ b/starts/meaning-vm/level0.cpp @@ -9,6 +9,8 @@ using namespace intellect::level0; int main() { + std::cout << allocated() << " allocated" << std::endl; + ref store = alloc(concepts::allocations()); out(store); ref a = alloc(store); out(a); ref b = alloc(store); out(b); diff --git a/starts/meaning-vm/level1.cpp b/starts/meaning-vm/level1.cpp index aa945b3..3c1a634 100644 --- a/starts/meaning-vm/level1.cpp +++ b/starts/meaning-vm/level1.cpp @@ -65,7 +65,7 @@ int main() std::cout << apple.dump("dumped", true) << std::endl; std::cout << intellect::level0::allocated() << " allocated" << std::endl; - intellect::level0::dealloc(intellect::level0::concepts::allocations(), intellect::level0::concepts::allocations()); + intellect::level0::dealloc(intellect::level0::concepts::allocations(), intellect::level0::concepts::level0allocations()); std::cout << intellect::level0::allocated() << " allocated" << std::endl; return 0; diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile index 325a07c..637c4fe 100644 --- a/starts/meaning-vm/makefile +++ b/starts/meaning-vm/makefile @@ -1,4 +1,4 @@ -CXXFLAGS=-Wall -Werror -std=gnu++17 -fno-operator-names -ggdb -O0 +CXXFLAGS=-Wall -Werror -Wno-error=deprecated-declarations -std=gnu++17 -fno-operator-names -ggdb -O0 LINK.o=$(LINK.cc) all: level0 level1 habit-starts/rhythm -- cgit v1.2.3