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::vector<bool> m_active_indices{};
|
||||
bool m_has_deleted_elements = false;
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -258,6 +259,7 @@ public:
|
|||
|
||||
Property_container(const Property_container<Index>& other) {
|
||||
m_active_indices = other.m_active_indices;
|
||||
m_has_deleted_elements = other.m_has_deleted_elements;
|
||||
|
||||
for (auto [name, array] : other.m_properties) {
|
||||
// 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.
|
||||
Property_container<Index>& operator=(const Property_container<Index>& other) {
|
||||
m_active_indices = other.m_active_indices;
|
||||
m_has_deleted_elements = other.m_has_deleted_elements;
|
||||
|
||||
for (auto [name, array] : other.m_properties) {
|
||||
// search if property already exists
|
||||
|
|
@ -295,6 +298,7 @@ public:
|
|||
// This is not exactly an assignment as existing unique properties are kept.
|
||||
Property_container<Index>& operator=(Property_container<Index>&& other) {
|
||||
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) {
|
||||
// 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
|
||||
other.reserve(0);
|
||||
other.resize(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -441,16 +445,15 @@ 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) {
|
||||
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);
|
||||
|
||||
m_has_deleted_elements = false;
|
||||
}
|
||||
|
||||
[[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() {
|
||||
|
||||
// Expand the storage and return the last element
|
||||
reserve(capacity() + 1);
|
||||
m_active_indices.back() = true;
|
||||
m_active_indices.push_back(true);
|
||||
|
||||
for (auto [name, array] : m_properties)
|
||||
array->reserve(capacity());
|
||||
|
||||
auto first_new_index = Index(capacity() - 1);
|
||||
reset(first_new_index);
|
||||
return first_new_index;
|
||||
|
|
@ -469,6 +475,9 @@ public:
|
|||
|
||||
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
|
||||
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()) {
|
||||
|
|
@ -478,20 +487,27 @@ public:
|
|||
return index;
|
||||
}
|
||||
|
||||
m_has_deleted_elements = false;
|
||||
|
||||
return emplace_back();
|
||||
}
|
||||
|
||||
Index emplace_group_back(std::size_t n) {
|
||||
|
||||
// Expand the storage and return the start of the new region
|
||||
reserve(capacity() + n);
|
||||
for (auto it = m_active_indices.end() - n; it < m_active_indices.end(); ++it)
|
||||
*it = true;
|
||||
m_active_indices.resize(capacity() + n, true);
|
||||
|
||||
for (auto [name, array] : m_properties)
|
||||
array->reserve(capacity());
|
||||
|
||||
return Index(capacity() - 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();
|
||||
while (search_start != m_active_indices.end()) {
|
||||
|
||||
|
|
@ -544,6 +560,7 @@ public:
|
|||
|
||||
void erase(Index i) {
|
||||
m_active_indices[i] = false;
|
||||
m_has_deleted_elements = true;
|
||||
for (auto [name, array]: m_properties)
|
||||
array->reset(i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,6 @@ void test_element_access() {
|
|||
|
||||
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
|
||||
assert(properties.emplace() == 0);
|
||||
assert(properties.emplace() == 1);
|
||||
|
|
@ -61,7 +56,6 @@ void test_element_access() {
|
|||
auto& floats = properties.add_property("floats", 6.0f);
|
||||
|
||||
// The new property array should already be of the right size
|
||||
assert(floats.capacity() == 100);
|
||||
assert(properties.size() == 3);
|
||||
|
||||
// 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
|
||||
properties.erase(1);
|
||||
assert(properties.size() == 2);
|
||||
assert(properties.capacity() == 100);
|
||||
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
|
||||
assert(properties.emplace() == 1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue