Skip to content

Commit

Permalink
Remove dead code
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-sparus committed May 30, 2024
1 parent d383f05 commit f826285
Show file tree
Hide file tree
Showing 16 changed files with 948 additions and 3,634 deletions.
20 changes: 0 additions & 20 deletions immer/extra/persist/box/pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ get_box_id(output_pool<T, MemoryPolicy> pool,
return {std::move(pool), id};
}

template <typename T, typename MemoryPolicy>
inline auto make_output_pool_for(const immer::box<T, MemoryPolicy>&)
{
return output_pool<T, MemoryPolicy>{};
}

template <typename T, typename MemoryPolicy>
struct input_pool
{
Expand Down Expand Up @@ -192,20 +186,6 @@ loader<T, MemoryPolicy> make_loader_for(const immer::box<T, MemoryPolicy>&,
return loader<T, MemoryPolicy>{std::move(pool)};
}

template <typename T, typename MemoryPolicy, class F>
auto transform_pool(const input_pool<T, MemoryPolicy>& pool, F&& func)
{
using U = std::decay_t<decltype(func(std::declval<T>()))>;
auto boxes = immer::vector<immer::box<U, MemoryPolicy>>{};
for (const auto& item : pool.boxes) {
boxes = std::move(boxes).push_back(func(item.get()));
}

return input_pool<U, MemoryPolicy>{
.boxes = std::move(boxes),
};
}

} // namespace immer::persist::box

namespace immer::persist {
Expand Down
283 changes: 217 additions & 66 deletions immer/extra/persist/champ/input.hpp
Original file line number Diff line number Diff line change
@@ -1,103 +1,254 @@
#pragma once

#include <immer/extra/persist/champ/pool.hpp>
#include <immer/extra/persist/errors.hpp>
#include <immer/extra/persist/node_ptr.hpp>

#include <immer/flex_vector.hpp>

#include <boost/hana/functional/id.hpp>
#include <boost/range/adaptor/indexed.hpp>

#include <spdlog/spdlog.h>

namespace immer::persist {
namespace champ {

template <class T, immer::detail::hamts::bits_t B>
struct output_pool_builder
class children_count_corrupted_exception : public pool_exception
{
nodes_save<T, B> pool;
public:
children_count_corrupted_exception(node_id id,
std::uint64_t nodemap,
std::size_t expected_count,
std::size_t real_count)
: pool_exception{fmt::format(
"Loaded container is corrupted. Inner "
"node ID {} has nodemap {} which means it should have {} "
"children but it has {}",
id,
nodemap,
expected_count,
real_count)}
{
}
};

void visit_inner(const auto* node, auto depth)
class data_count_corrupted_exception : public pool_exception
{
public:
data_count_corrupted_exception(node_id id,
std::uint64_t datamap,
std::size_t expected_count,
std::size_t real_count)
: pool_exception{fmt::format(
"Loaded container is corrupted. Inner "
"node ID {} has datamap {} which means it should contain {} "
"values but it has {}",
id,
datamap,
expected_count,
real_count)}
{
auto id = get_node_id(node);
if (pool.inners.count(id)) {
return;
}
}
};

auto node_info = inner_node_save<T, B>{
.nodemap = node->nodemap(),
.datamap = node->datamap(),
};
template <class T,
typename Hash,
typename Equal,
typename MemoryPolicy,
immer::detail::hamts::bits_t B,
typename NodesLoad = nodes_load<T, B>,
typename TransformF = boost::hana::id_t>
class nodes_loader
{
public:
using champ_t =
immer::detail::hamts::champ<T, Hash, Equal, MemoryPolicy, B>;
using node_t = typename champ_t::node_t;
using node_ptr = immer::persist::node_ptr<node_t>;

using values_t = immer::flex_vector<immer::array<T>>;

explicit nodes_loader(NodesLoad pool)
requires std::is_same_v<TransformF, boost::hana::id_t>
: pool_{std::move(pool)}
{
}

explicit nodes_loader(NodesLoad pool, TransformF transform)
: pool_{std::move(pool)}
, transform_{std::move(transform)}
{
}

if (node->datamap()) {
node_info.values = {node->values(),
node->values() + node->data_count()};
std::pair<node_ptr, values_t> load_collision(node_id id)
{
if (auto* p = collisions_.find(id)) {
return *p;
}
if (node->nodemap()) {
auto fst = node->children();
auto lst = fst + node->children_count();
for (; fst != lst; ++fst) {
node_info.children =
std::move(node_info.children).push_back(get_node_id(*fst));
visit(*fst, depth + 1);
}

if (id.value >= pool_.size()) {
throw invalid_node_id{id};
}

pool.inners = std::move(pool.inners).set(id, node_info);
const auto& node_info = pool_[id.value];
const auto values = get_values(node_info.values.data);

const auto n = values.size();
auto node = node_ptr{node_t::make_collision_n(n),
[](auto* ptr) { node_t::delete_collision(ptr); }};
immer::detail::uninitialized_copy(
values.begin(), values.end(), node.get()->collisions());
auto result = std::make_pair(std::move(node), values_t{values});
collisions_ = std::move(collisions_).set(id, result);
return result;
}

void visit_collision(const auto* node)
std::pair<node_ptr, values_t> load_inner(node_id id)
{
auto id = get_node_id(node);
if (pool.inners.count(id)) {
return;
if (auto* p = inners_.find(id)) {
return *p;
}

pool.inners = std::move(pool.inners)
.set(id,
inner_node_save<T, B>{
.values = {node->collisions(),
node->collisions() +
node->collision_count()},
.collisions = true,
});
if (id.value >= pool_.size()) {
throw invalid_node_id{id};
}

const auto& node_info = pool_[id.value];

const auto children_count = node_info.children.size();
const auto values_count = node_info.values.data.size();

// Loading validation
{
const auto expected_count =
immer::detail::hamts::popcount(node_info.nodemap);
if (expected_count != children_count) {
throw children_count_corrupted_exception{
id, node_info.nodemap, expected_count, children_count};
}
}

{
const auto expected_count =
immer::detail::hamts::popcount(node_info.datamap);
if (expected_count != values_count) {
throw data_count_corrupted_exception{
id, node_info.datamap, expected_count, values_count};
}
}

const auto node_values = get_values(node_info.values.data);

auto values = values_t{};

// Load children
const auto children = [&values, &node_info, this] {
auto [children_ptrs, children_values] =
load_children(node_info.children);

if (!children_values.empty()) {
values = std::move(values) + children_values;
}

/**
* NOTE: Be careful with release_full and exceptions, nodes will not
* be freed automatically.
*/
auto result = immer::vector<ptr_with_deleter<node_t>>{};
for (auto& child : children_ptrs) {
result = std::move(result).push_back(
std::move(child).release_full());
}
return result;
}();
const auto delete_children = [children]() {
for (const auto& ptr : children) {
ptr.dec();
}
};

auto inner =
node_ptr{node_t::make_inner_n(children_count, values_count),
[delete_children](auto* ptr) {
node_t::delete_inner(ptr);
delete_children();
}};
inner.get()->impl.d.data.inner.nodemap = node_info.nodemap;
inner.get()->impl.d.data.inner.datamap = node_info.datamap;

// Values
if (values_count) {
immer::detail::uninitialized_copy(
node_values.begin(), node_values.end(), inner.get()->values());
values = std::move(values).push_back(node_values);
}

// Set children
for (const auto& [index, child_ptr] :
boost::adaptors::index(children)) {
inner.get()->children()[index] = child_ptr.ptr;
}

inners_ = std::move(inners_).set(id, std::make_pair(inner, values));
return {std::move(inner), std::move(values)};
}

void visit(const auto* node, immer::detail::hamts::count_t depth)
std::pair<node_ptr, values_t> load_some_node(node_id id)
{
using immer::detail::hamts::max_depth;
if (id.value >= pool_.size()) {
throw invalid_node_id{id};
}

if (depth < max_depth<B>) {
visit_inner(node, depth);
if (pool_[id.value].collisions) {
return load_collision(id);
} else {
visit_collision(node);
return load_inner(id);
}
}

node_id get_node_id(auto* ptr)
std::pair<std::vector<node_ptr>, values_t>
load_children(const immer::vector<node_id>& children_ids)
{
auto [pool2, id] =
immer::persist::champ::get_node_id(std::move(pool), ptr);
pool = std::move(pool2);
return id;
}
};
auto children = std::vector<node_ptr>{};
auto values = values_t{};
for (const auto& child_node_id : children_ids) {
auto [child, child_values] = load_some_node(child_node_id);
if (!child) {
throw pool_exception{
fmt::format("Failed to load node ID {}", child_node_id)};
}

template <typename T,
typename Hash,
typename Equal,
typename MemoryPolicy,
immer::detail::hamts::bits_t B,
class Pool>
auto save_nodes(
const immer::detail::hamts::champ<T, Hash, Equal, MemoryPolicy, B>& champ,
Pool pool)
{
using champ_t = std::decay_t<decltype(champ)>;
using node_t = typename champ_t::node_t;
if (!child_values.empty()) {
values = std::move(values) + child_values;
}

children.push_back(std::move(child));
}
return {std::move(children), std::move(values)};
}

auto save = output_pool_builder<typename node_t::value_t, B>{
.pool = std::move(pool),
};
save.visit(champ.root, 0);
private:
immer::array<T> get_values(const auto& array) const
{
if constexpr (std::is_same_v<TransformF, boost::hana::id_t>) {
return array;
} else {
auto transformed_values = std::vector<T>{};
for (const auto& item : array) {
transformed_values.push_back(transform_(item));
}
return immer::array<T>{transformed_values.begin(),
transformed_values.end()};
}
}

return std::move(save.pool);
}
private:
const NodesLoad pool_;
const TransformF transform_;
immer::map<node_id, std::pair<node_ptr, values_t>> collisions_;
immer::map<node_id, std::pair<node_ptr, values_t>> inners_;
};

} // namespace champ
} // namespace immer::persist
Loading

0 comments on commit f826285

Please sign in to comment.