Files
test2/source/blender/makesdna/DNA_array_utils.hh
Jacques Lucke ae6aeb3cc3 Spreadsheet: garbage collect long unavailable columns
Previously, it was possible for the number of stored columns per table to grow
unbounded. While this likely isn't a problem in practice in most cases, one can
imagine cases where people temporarily have thousands of attributes when are
then never used again. We shouldn't have to store any data for these columns
forever.

This patch adds some simple garbage collection mechanism that keeps the number
of stored unavailable columns  per spreadsheet table below a certain threshold
(50 currently). Least recently used columns are removed first.

Pull Request: https://projects.blender.org/blender/blender/pulls/139469
2025-05-27 06:29:06 +02:00

128 lines
3.6 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup DNA
*
* Contains functions that help dealing with arrays that are stored in DNA. Due to the constraints
* of DNA, all structs are trivial from the language's point of view (`std::is_trivial_v`).
* However, semantically, these types may have non-trivial copy-constructors and destructors.
*/
#include "MEM_guardedalloc.h"
#include "BLI_function_ref.hh"
#include "BLI_index_range.hh"
#include "BLI_utildefines.h"
namespace blender::dna::array {
/**
* Removes an element from the array and shifts the elements after it towards the front.
*/
template<typename T>
inline void remove_index(
T **items, int *items_num, int *active_index, const int index, void (*destruct_item)(T *))
{
static_assert(std::is_trivial_v<T>);
BLI_assert(index >= 0);
BLI_assert(index < *items_num);
const int old_items_num = *items_num;
const int new_items_num = old_items_num - 1;
T *old_items = *items;
T *new_items = MEM_calloc_arrayN<T>(new_items_num, __func__);
std::copy_n(old_items, index, new_items);
std::copy_n(old_items + index + 1, old_items_num - index - 1, new_items + index);
destruct_item(&old_items[index]);
MEM_freeN(old_items);
*items = new_items;
*items_num = new_items_num;
if (active_index) {
const int old_active_index = active_index ? *active_index : 0;
const int new_active_index = std::max(
0, old_active_index == new_items_num ? new_items_num - 1 : old_active_index);
*active_index = new_active_index;
}
}
/**
* Removes all elements for which the predicate is true. The remaining ones stay in the order they
* were in before.
*/
template<typename T>
inline void remove_if(T **items,
int *items_num,
FunctionRef<bool(const T &)> predicate,
void (*destruct_item)(T *))
{
static_assert(std::is_trivial_v<T>);
/* This sorts the items-to-remove to the back. */
const int remaining = std::stable_partition(*items,
*items + *items_num,
[&](const T &value) { return !predicate(value); }) -
*items;
for (const int i : IndexRange::from_begin_end(remaining, *items_num)) {
destruct_item(&(*items)[i]);
}
*items_num = remaining;
}
/**
* Removes all elements from an array and frees it.
*/
template<typename T>
inline void clear(T **items, int *items_num, int *active_index, void (*destruct_item)(T *))
{
static_assert(std::is_trivial_v<T>);
for (const int i : IndexRange(*items_num)) {
destruct_item(&(*items)[i]);
}
MEM_SAFE_FREE(*items);
*items_num = 0;
if (active_index) {
*active_index = 0;
}
}
/**
* Moves one element from one index to another, moving other elements if necessary.
*/
template<typename T>
inline void move_index(T *items, const int items_num, const int from_index, const int to_index)
{
static_assert(std::is_trivial_v<T>);
BLI_assert(from_index >= 0);
BLI_assert(from_index < items_num);
BLI_assert(to_index >= 0);
BLI_assert(to_index < items_num);
UNUSED_VARS_NDEBUG(items_num);
if (from_index == to_index) {
return;
}
if (from_index < to_index) {
const T tmp = items[from_index];
for (int i = from_index; i < to_index; i++) {
items[i] = items[i + 1];
}
items[to_index] = tmp;
}
else if (from_index > to_index) {
const T tmp = items[from_index];
for (int i = from_index; i > to_index; i--) {
items[i] = items[i - 1];
}
items[to_index] = tmp;
}
}
} // namespace blender::dna::array