diff options
Diffstat (limited to 'starts')
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.cpp | 112 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.hpp | 4 | ||||
-rw-r--r-- | starts/meaning-vm/level0.cpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/level1.cpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/makefile | 2 |
5 files changed, 93 insertions, 29 deletions
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 <unordered_set> +#include <memory> +#include <unordered_map> namespace intellect { namespace level0 { static auto & index() { - static std::unordered_set<ref, std::hash<concept*>> index; + static std::unordered_map<ref, std::unique_ptr<concept>, std::hash<concept*>> 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<decltype(index())>::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 |