From 160ba647becf04fbebb33df47a826f6dd55abb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pedro=20Bol=C3=ADvar=20Puente?= Date: Thu, 2 Jun 2022 11:45:52 +0200 Subject: [PATCH] Improve sequential initialization of HAMTs With this implementation, it uses transients also when using a tracing garbage collector -- before it would be optimized only when using reference counting. --- immer/detail/hamts/champ.hpp | 22 ++++++++++++++++++++++ immer/map.hpp | 12 ++++-------- immer/set.hpp | 12 ++++-------- immer/table.hpp | 18 +++++++----------- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/immer/detail/hamts/champ.hpp b/immer/detail/hamts/champ.hpp index 292527f4..5f635097 100644 --- a/immer/detail/hamts/champ.hpp +++ b/immer/detail/hamts/champ.hpp @@ -89,6 +89,28 @@ struct champ node_t::delete_deep(root, 0); } + template + static auto from_initializer_list(std::initializer_list values) + { + auto e = owner_t{}; + auto result = champ{empty()}; + for (auto&& v : values) + result.add_mut(e, v); + return result; + } + + template , bool> = true> + static auto from_range(Iter first, Sent last) + { + auto e = owner_t{}; + auto result = champ{empty()}; + for (; first != last; ++first) + result.add_mut(e, *first); + return result; + } + template void for_each_chunk(Fn&& fn) const { diff --git a/immer/map.hpp b/immer/map.hpp index 33315ad9..acbbc0b1 100644 --- a/immer/map.hpp +++ b/immer/map.hpp @@ -170,10 +170,8 @@ class map * Constructs a map containing the elements in `values`. */ map(std::initializer_list values) - { - for (auto&& v : values) - *this = std::move(*this).insert(v); - } + : impl_{impl_t::from_initializer_list(values)} + {} /*! * Constructs a map containing the elements in the range @@ -184,10 +182,8 @@ class map std::enable_if_t, bool> = true> map(Iter first, Sent last) - { - for (; first != last; ++first) - *this = std::move(*this).insert(*first); - } + : impl_{impl_t::from_range(first, last)} + {} /*! * Default constructor. It creates a map of `size() == 0`. It diff --git a/immer/set.hpp b/immer/set.hpp index 247ef83f..a8199b22 100644 --- a/immer/set.hpp +++ b/immer/set.hpp @@ -95,10 +95,8 @@ class set * Constructs a set containing the elements in `values`. */ set(std::initializer_list values) - { - for (auto&& v : values) - *this = std::move(*this).insert(v); - } + : impl_{impl_t::from_initializer_list(values)} + {} /*! * Constructs a set containing the elements in the range @@ -109,10 +107,8 @@ class set std::enable_if_t, bool> = true> set(Iter first, Sent last) - { - for (; first != last; ++first) - *this = std::move(*this).insert(*first); - } + : impl_{impl_t::from_range(first, last)} + {} /*! * Returns an iterator pointing at the first element of the diff --git a/immer/table.hpp b/immer/table.hpp index dd45012c..c4118054 100644 --- a/immer/table.hpp +++ b/immer/table.hpp @@ -186,10 +186,8 @@ class table * Constructs a table containing the elements in `values`. */ table(std::initializer_list values) - { - for (auto&& v : values) - *this = std::move(*this).insert(v); - } + : impl_{impl_t::from_initializer_list(values)} + {} /*! * Constructs a table containing the elements in the range @@ -200,10 +198,8 @@ class table std::enable_if_t, bool> = true> table(Iter first, Sent last) - { - for (; first != last; ++first) - *this = std::move(*this).insert(*first); - } + : impl_{impl_t::from_range(first, last)} + {} /*! * Default constructor. It creates a table of `size() == 0`. It @@ -467,7 +463,7 @@ class table table&& update_move(std::true_type, key_type k, Fn&& fn) { impl_.template update_mut( - std::move(k), std::forward(fn)); + {}, std::move(k), std::forward(fn)); return std::move(*this); } @@ -475,8 +471,8 @@ class table table update_move(std::false_type, key_type k, Fn&& fn) { return impl_ - .template update_mut( - {}, std::move(k), std::forward(fn)); + .template update( + std::move(k), std::forward(fn)); } table&& erase_move(std::true_type, const key_type& value)