summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/level-0/memorystore.cpp
blob: 61f8ec073fe2c75811a2034bd1dc7f87a442904f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "memorystore.hpp"
#include "concept.hpp"
#include "errors.hpp"
#include "ref.hpp"

#include <unordered_set>

namespace intellect {
namespace level0 {

static auto & index()
{
	static std::unordered_set<ref, 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; };
}

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;
	alloc((ref)r, source);
	index().insert(r);
	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, ref source) {
	for (ref r2 : index()) {
		if (r2 == 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 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 ghost : ours) {
		concept * referenced = intellect::level0::referenced(ghost, source);
		if (referenced) {
			throw still_referenced_by(ghost, referenced);
		}
	}
	delete (concept*)r;
}

std::size_t allocated()
{
	return index().size();
}

}
}