Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

store extra information in iterator needed to find base of allocation #190

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
49 changes: 45 additions & 4 deletions immer/detail/hamts/champ_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,38 @@

#include <immer/detail/hamts/champ.hpp>
#include <immer/detail/iterator_facade.hpp>
#include <immer/relocation/gc_relocation_policy.hpp>

namespace immer {
namespace detail {
namespace hamts {

template <typename Policy, bits_t B>
struct relocation_info_t
{
void reset() {}
void increment() {}
void step_right(count_t) {}
void step_down(count_t) {}
};

template <bits_t B>
struct relocation_info_t<gc_relocation_policy, B>
{
count_t cur_off_;
std::uint8_t path_off_[max_depth<B>] = {
0,
};

void reset() { cur_off_ = 0; }

void increment() { cur_off_++; }

void step_right(count_t depth) { ++path_off_[depth - 1]; }

void step_down(count_t depth) { path_off_[depth - 1] = 0; }
};
dwightguth marked this conversation as resolved.
Show resolved Hide resolved

template <typename T, typename Hash, typename Eq, typename MP, bits_t B>
struct champ_iterator
: iterator_facade<champ_iterator<T, Hash, Eq, MP, B>,
Expand All @@ -24,14 +51,17 @@ struct champ_iterator
std::ptrdiff_t,
const T*>
{
using tree_t = champ<T, Hash, Eq, MP, B>;
using node_t = typename tree_t::node_t;
using memory = MP;
using relocation = typename memory::relocation;
using tree_t = champ<T, Hash, Eq, MP, B>;
using node_t = typename tree_t::node_t;

struct end_t
{};

champ_iterator(const tree_t& v)
: depth_{0}
, relocation_info_{}
{
if (v.root->datamap()) {
cur_ = v.root->values();
Expand All @@ -47,6 +77,7 @@ struct champ_iterator
: cur_{nullptr}
, end_{nullptr}
, depth_{0}
, relocation_info_{}
{
path_[0] = &v.root;
}
Expand All @@ -55,6 +86,7 @@ struct champ_iterator
: cur_{other.cur_}
, end_{other.end_}
, depth_{other.depth_}
, relocation_info_{other.relocation_info_}
{
std::copy(other.path_, other.path_ + depth_ + 1, path_);
}
Expand All @@ -68,10 +100,12 @@ struct champ_iterator
node_t* const* path_[max_depth<B> + 1] = {
0,
};
relocation_info_t<relocation, B> relocation_info_;

void increment()
{
++cur_;
relocation_info_.increment();
ensure_valid_();
}

Expand All @@ -83,16 +117,19 @@ struct champ_iterator
if (parent->nodemap()) {
++depth_;
path_[depth_] = parent->children();
auto child = *path_[depth_];
relocation_info_.step_down(depth_);
auto child = *path_[depth_];
assert(child);
if (depth_ < max_depth<B>) {
if (child->datamap()) {
cur_ = child->values();
end_ = cur_ + child->data_count();
relocation_info_.reset();
}
} else {
cur_ = child->collisions();
end_ = cur_ + child->collision_count();
relocation_info_.reset();
}
return true;
}
Expand All @@ -108,16 +145,19 @@ struct champ_iterator
auto next = path_[depth_] + 1;
if (next < last) {
path_[depth_] = next;
auto child = *path_[depth_];
relocation_info_.step_right(depth_);
auto child = *path_[depth_];
assert(child);
if (depth_ < max_depth<B>) {
if (child->datamap()) {
cur_ = child->values();
end_ = cur_ + child->data_count();
relocation_info_.reset();
}
} else {
cur_ = child->collisions();
end_ = cur_ + child->collision_count();
relocation_info_.reset();
}
return true;
}
Expand All @@ -136,6 +176,7 @@ struct champ_iterator
// end of sequence
assert(depth_ == 0);
cur_ = end_ = nullptr;
relocation_info_.reset();
return;
}
}
Expand Down
5 changes: 4 additions & 1 deletion immer/memory_policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <immer/refcount/no_refcount_policy.hpp>
#include <immer/refcount/refcount_policy.hpp>
#include <immer/refcount/unsafe_refcount_policy.hpp>
#include <immer/relocation/no_relocation_policy.hpp>
#include <immer/transience/gc_transience_policy.hpp>
#include <immer/transience/no_transience_policy.hpp>
#include <type_traits>
Expand Down Expand Up @@ -90,13 +91,15 @@ template <typename HeapPolicy,
bool PreferFewerBiggerObjects =
get_prefer_fewer_bigger_objects_v<HeapPolicy>,
bool UseTransientRValues =
get_use_transient_rvalues_v<RefcountPolicy>>
get_use_transient_rvalues_v<RefcountPolicy>,
typename RelocationPolicy = no_relocation_policy>
struct memory_policy
{
using heap = HeapPolicy;
using refcount = RefcountPolicy;
using transience = TransiencePolicy;
using lock = LockPolicy;
using relocation = RelocationPolicy;
dwightguth marked this conversation as resolved.
Show resolved Hide resolved

static constexpr bool prefer_fewer_bigger_objects =
PreferFewerBiggerObjects;
Expand Down
22 changes: 22 additions & 0 deletions immer/relocation/gc_relocation_policy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// immer: immutable data structures for C++
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
//
// This software is distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
//

#pragma once

namespace immer {

/*!
* Enables relocation information tracking; used when a relocating garbage
* collector is present in the final system.
*/
struct gc_relocation_policy
{
gc_relocation_policy(){};
};

} // namespace immer
22 changes: 22 additions & 0 deletions immer/relocation/no_relocation_policy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// immer: immutable data structures for C++
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
//
// This software is distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
//

#pragma once

namespace immer {

/*!
* Disables relocation information tracking; used when a relocating garbage
* collector is not present in the final system.
*/
struct no_relocation_policy
{
no_relocation_policy(){};
};

} // namespace immer