mirror of https://github.com/CGAL/cgal
use simple deleted flag instead of tracking inactive indices
removing Property_container::reserve as it basically adds inactive indices and thus means linear insertion time
This commit is contained in:
parent
50fe8040ac
commit
bbf0a0e7ac
|
|
@ -248,6 +248,7 @@ class Property_container {
|
||||||
|
|
||||||
std::multimap<std::string, std::shared_ptr<Property_array_base<Index>>> m_properties;
|
std::multimap<std::string, std::shared_ptr<Property_array_base<Index>>> m_properties;
|
||||||
std::vector<bool> m_active_indices{};
|
std::vector<bool> m_active_indices{};
|
||||||
|
bool m_has_deleted_elements = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -258,6 +259,7 @@ public:
|
||||||
|
|
||||||
Property_container(const Property_container<Index>& other) {
|
Property_container(const Property_container<Index>& other) {
|
||||||
m_active_indices = other.m_active_indices;
|
m_active_indices = other.m_active_indices;
|
||||||
|
m_has_deleted_elements = other.m_has_deleted_elements;
|
||||||
|
|
||||||
for (auto [name, array] : other.m_properties) {
|
for (auto [name, array] : other.m_properties) {
|
||||||
// todo: this could probably be made faster using emplace_hint
|
// todo: this could probably be made faster using emplace_hint
|
||||||
|
|
@ -273,6 +275,7 @@ public:
|
||||||
// This is not exactly an assignment as existing unique properties are kept.
|
// This is not exactly an assignment as existing unique properties are kept.
|
||||||
Property_container<Index>& operator=(const Property_container<Index>& other) {
|
Property_container<Index>& operator=(const Property_container<Index>& other) {
|
||||||
m_active_indices = other.m_active_indices;
|
m_active_indices = other.m_active_indices;
|
||||||
|
m_has_deleted_elements = other.m_has_deleted_elements;
|
||||||
|
|
||||||
for (auto [name, array] : other.m_properties) {
|
for (auto [name, array] : other.m_properties) {
|
||||||
// search if property already exists
|
// search if property already exists
|
||||||
|
|
@ -295,6 +298,7 @@ public:
|
||||||
// This is not exactly an assignment as existing unique properties are kept.
|
// This is not exactly an assignment as existing unique properties are kept.
|
||||||
Property_container<Index>& operator=(Property_container<Index>&& other) {
|
Property_container<Index>& operator=(Property_container<Index>&& other) {
|
||||||
m_active_indices = std::move(other.m_active_indices);
|
m_active_indices = std::move(other.m_active_indices);
|
||||||
|
m_has_deleted_elements = other.m_has_deleted_elements;
|
||||||
|
|
||||||
for (auto [name, array] : other.m_properties) {
|
for (auto [name, array] : other.m_properties) {
|
||||||
// search if property already exists
|
// search if property already exists
|
||||||
|
|
@ -312,7 +316,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// The moved-from property map should retain all of its properties, but contain 0 elements
|
// The moved-from property map should retain all of its properties, but contain 0 elements
|
||||||
other.reserve(0);
|
other.resize(0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,16 +445,15 @@ public:
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void reserve(std::size_t n) {
|
|
||||||
m_active_indices.resize(n);
|
|
||||||
for (auto [name, array]: m_properties)
|
|
||||||
array->reserve(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(std::size_t n) {
|
void resize(std::size_t n) {
|
||||||
reserve(n);
|
|
||||||
|
m_active_indices.resize(n);
|
||||||
|
for (auto [name, array] : m_properties)
|
||||||
|
array->reserve(n);
|
||||||
|
|
||||||
std::fill(m_active_indices.begin(), m_active_indices.end(), true);
|
std::fill(m_active_indices.begin(), m_active_indices.end(), true);
|
||||||
|
|
||||||
|
m_has_deleted_elements = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::size_t size() const { return std::count(m_active_indices.begin(), m_active_indices.end(), true); }
|
[[nodiscard]] std::size_t size() const { return std::count(m_active_indices.begin(), m_active_indices.end(), true); }
|
||||||
|
|
@ -460,8 +463,11 @@ public:
|
||||||
Index emplace_back() {
|
Index emplace_back() {
|
||||||
|
|
||||||
// Expand the storage and return the last element
|
// Expand the storage and return the last element
|
||||||
reserve(capacity() + 1);
|
m_active_indices.push_back(true);
|
||||||
m_active_indices.back() = true;
|
|
||||||
|
for (auto [name, array] : m_properties)
|
||||||
|
array->reserve(capacity());
|
||||||
|
|
||||||
auto first_new_index = Index(capacity() - 1);
|
auto first_new_index = Index(capacity() - 1);
|
||||||
reset(first_new_index);
|
reset(first_new_index);
|
||||||
return first_new_index;
|
return first_new_index;
|
||||||
|
|
@ -469,6 +475,9 @@ public:
|
||||||
|
|
||||||
Index emplace() {
|
Index emplace() {
|
||||||
|
|
||||||
|
if (!m_has_deleted_elements)
|
||||||
|
return emplace_back();
|
||||||
|
|
||||||
// If there are empty slots, return the index of one of them and mark it as full
|
// If there are empty slots, return the index of one of them and mark it as full
|
||||||
auto first_unused = std::find_if(m_active_indices.begin(), m_active_indices.end(), [](bool used) { return !used; });
|
auto first_unused = std::find_if(m_active_indices.begin(), m_active_indices.end(), [](bool used) { return !used; });
|
||||||
if (first_unused != m_active_indices.end()) {
|
if (first_unused != m_active_indices.end()) {
|
||||||
|
|
@ -478,20 +487,27 @@ public:
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_has_deleted_elements = false;
|
||||||
|
|
||||||
return emplace_back();
|
return emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Index emplace_group_back(std::size_t n) {
|
Index emplace_group_back(std::size_t n) {
|
||||||
|
|
||||||
// Expand the storage and return the start of the new region
|
// Expand the storage and return the start of the new region
|
||||||
reserve(capacity() + n);
|
m_active_indices.resize(capacity() + n, true);
|
||||||
for (auto it = m_active_indices.end() - n; it < m_active_indices.end(); ++it)
|
|
||||||
*it = true;
|
for (auto [name, array] : m_properties)
|
||||||
|
array->reserve(capacity());
|
||||||
|
|
||||||
return Index(capacity() - n);
|
return Index(capacity() - n);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index emplace_group(std::size_t n) {
|
Index emplace_group(std::size_t n) {
|
||||||
|
|
||||||
|
if (!m_has_deleted_elements)
|
||||||
|
return emplace_group_back(n);
|
||||||
|
|
||||||
auto search_start = m_active_indices.begin();
|
auto search_start = m_active_indices.begin();
|
||||||
while (search_start != m_active_indices.end()) {
|
while (search_start != m_active_indices.end()) {
|
||||||
|
|
||||||
|
|
@ -544,6 +560,7 @@ public:
|
||||||
|
|
||||||
void erase(Index i) {
|
void erase(Index i) {
|
||||||
m_active_indices[i] = false;
|
m_active_indices[i] = false;
|
||||||
|
m_has_deleted_elements = true;
|
||||||
for (auto [name, array]: m_properties)
|
for (auto [name, array]: m_properties)
|
||||||
array->reset(i);
|
array->reset(i);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,6 @@ void test_element_access() {
|
||||||
|
|
||||||
auto& integers = properties.add_property("integers", 5);
|
auto& integers = properties.add_property("integers", 5);
|
||||||
|
|
||||||
// Reserve space for 100 elements
|
|
||||||
properties.reserve(100);
|
|
||||||
assert(properties.capacity() == 100);
|
|
||||||
assert(properties.size() == 0);
|
|
||||||
|
|
||||||
// Newly emplaced elements should go at the front
|
// Newly emplaced elements should go at the front
|
||||||
assert(properties.emplace() == 0);
|
assert(properties.emplace() == 0);
|
||||||
assert(properties.emplace() == 1);
|
assert(properties.emplace() == 1);
|
||||||
|
|
@ -61,7 +56,6 @@ void test_element_access() {
|
||||||
auto& floats = properties.add_property("floats", 6.0f);
|
auto& floats = properties.add_property("floats", 6.0f);
|
||||||
|
|
||||||
// The new property array should already be of the right size
|
// The new property array should already be of the right size
|
||||||
assert(floats.capacity() == 100);
|
|
||||||
assert(properties.size() == 3);
|
assert(properties.size() == 3);
|
||||||
|
|
||||||
// Pre-existing elements should contain the default value
|
// Pre-existing elements should contain the default value
|
||||||
|
|
@ -87,9 +81,8 @@ void test_element_access() {
|
||||||
// Erase an element, and the size should be reduced
|
// Erase an element, and the size should be reduced
|
||||||
properties.erase(1);
|
properties.erase(1);
|
||||||
assert(properties.size() == 2);
|
assert(properties.size() == 2);
|
||||||
assert(properties.capacity() == 100);
|
|
||||||
assert(properties.active_list().size() == 2);
|
assert(properties.active_list().size() == 2);
|
||||||
assert(properties.inactive_list().size() == 98);
|
assert(properties.inactive_list().size() == 1);
|
||||||
|
|
||||||
// A newly emplaced element should take the empty slot
|
// A newly emplaced element should take the empty slot
|
||||||
assert(properties.emplace() == 1);
|
assert(properties.emplace() == 1);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue