Refactor: Make file-list cache struct non-trivial C++ one

Makes it possible to use non-trivial C++ types in `FileListEntryCache`.
I'm planning to use this for blender/blender!130543, to store status
information about downloaded previews. While it's possible to use
C-style types instead, this is easier and a worthwhile general
improvement.

I turned `FileList.filelist_cache` into an allocated pointer, so
`FileList` doesn't have to be ported to be a non-trivial type as well.
We probably want to do that too at some point.

Pull Request: https://projects.blender.org/blender/blender/pulls/141411
This commit is contained in:
Julian Eisel
2025-07-04 23:09:02 +02:00
committed by Julian Eisel
parent 58af30f9b9
commit 183420bd07

View File

@@ -163,40 +163,45 @@ struct FileListIntern {
#define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */
struct FileListEntryCache {
size_t size; /* The size of the cache... */
size_t size = 0; /* The size of the cache... */
int flags;
int flags = 0;
/* This one gathers all entries from both block and misc caches. Used for easy bulk-freeing. */
ListBase cached_entries;
ListBase cached_entries = {};
/* Block cache: all entries between start and end index.
* used for part of the list on display. */
FileDirEntry **block_entries;
int block_start_index, block_end_index, block_center_index, block_cursor;
FileDirEntry **block_entries = nullptr;
int block_start_index = 0;
int block_end_index = 0;
int block_center_index = 0;
int block_cursor = 0;
/* Misc cache: random indices, FIFO behavior.
* NOTE: Not 100% sure we actually need that, time will say. */
int misc_cursor;
int *misc_entries_indices;
GHash *misc_entries;
int misc_cursor = 0;
int *misc_entries_indices = nullptr;
GHash *misc_entries = nullptr;
/* Allows to quickly get a cached entry from its UID. */
GHash *uids;
GHash *uids = nullptr;
/* Previews handling. */
TaskPool *previews_pool;
ThreadQueue *previews_done;
TaskPool *previews_pool = nullptr;
ThreadQueue *previews_done = nullptr;
/** Counter for previews that are not fully loaded and ready to display yet. So includes all
* previews either in `previews_pool` or `previews_done`. #filelist_cache_previews_update() makes
* previews in `preview_done` ready for display, so the counter is decremented there. */
int previews_todo_count;
int previews_todo_count = 0;
FileListEntryCache();
~FileListEntryCache();
};
/** #FileListCache.flags */
enum {
FLC_IS_INIT = 1 << 0,
FLC_PREVIEWS_ACTIVE = 1 << 1,
FLC_PREVIEWS_ACTIVE = 1 << 0,
};
struct FileListEntryPreview {
@@ -254,7 +259,7 @@ struct FileList {
FileListIntern filelist_intern;
FileListEntryCache filelist_cache;
FileListEntryCache *filelist_cache;
/**
* We need to keep those info outside of actual file-list items,
@@ -1002,7 +1007,7 @@ void filelist_filter(FileList *filelist)
filelist->filelist.entries_filtered_num = num_filtered;
// printf("Filetered: %d over %d entries\n", num_filtered, filelist->filelist.entries_num);
filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
filelist_cache_clear(filelist->filelist_cache, filelist->filelist_cache->size);
filelist->flags &= ~FL_NEED_FILTERING;
MEM_freeN(filtered_tmp);
@@ -1673,7 +1678,7 @@ static bool filelist_file_preview_load_poll(const FileDirEntry *entry)
*/
static bool filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
@@ -1733,56 +1738,37 @@ static bool filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
return true;
}
static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
FileListEntryCache::FileListEntryCache() : size(FILELIST_ENTRYCACHESIZE_DEFAULT)
{
BLI_listbase_clear(&cache->cached_entries);
block_entries = static_cast<FileDirEntry **>(
MEM_mallocN(sizeof(*this->block_entries) * this->size, __func__));
cache->block_cursor = cache->block_start_index = cache->block_center_index =
cache->block_end_index = 0;
cache->block_entries = static_cast<FileDirEntry **>(
MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__));
this->misc_entries = BLI_ghash_ptr_new_ex(__func__, this->size);
this->misc_entries_indices = MEM_malloc_arrayN<int>(this->size, __func__);
copy_vn_i(this->misc_entries_indices, this->size, -1);
cache->misc_entries = BLI_ghash_ptr_new_ex(__func__, cache_size);
cache->misc_entries_indices = MEM_malloc_arrayN<int>(cache_size, __func__);
copy_vn_i(cache->misc_entries_indices, cache_size, -1);
cache->misc_cursor = 0;
cache->uids = BLI_ghash_new_ex(
BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__, cache_size * 2);
cache->size = cache_size;
cache->flags = FLC_IS_INIT;
cache->previews_todo_count = 0;
this->uids = BLI_ghash_new_ex(
BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__, this->size * 2);
}
static void filelist_cache_free(FileListEntryCache *cache)
FileListEntryCache::~FileListEntryCache()
{
if (!(cache->flags & FLC_IS_INIT)) {
return;
}
filelist_cache_previews_free(this);
filelist_cache_previews_free(cache);
MEM_freeN(this->block_entries);
MEM_freeN(cache->block_entries);
BLI_ghash_free(this->misc_entries, nullptr, nullptr);
MEM_freeN(this->misc_entries_indices);
BLI_ghash_free(cache->misc_entries, nullptr, nullptr);
MEM_freeN(cache->misc_entries_indices);
BLI_ghash_free(this->uids, nullptr, nullptr);
BLI_ghash_free(cache->uids, nullptr, nullptr);
LISTBASE_FOREACH_MUTABLE (FileDirEntry *, entry, &cache->cached_entries) {
LISTBASE_FOREACH_MUTABLE (FileDirEntry *, entry, &this->cached_entries) {
filelist_entry_free(entry);
}
BLI_listbase_clear(&cache->cached_entries);
}
static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
{
if (!(cache->flags & FLC_IS_INIT)) {
return;
}
filelist_cache_previews_clear(cache);
cache->block_cursor = cache->block_start_index = cache->block_center_index =
@@ -1813,7 +1799,7 @@ FileList *filelist_new(short type)
{
FileList *p = MEM_callocN<FileList>(__func__);
filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT);
p->filelist_cache = MEM_new<FileListEntryCache>("FileListEntryCache");
p->selection_state = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
p->filelist.entries_num = FILEDIR_NBR_ENTRIES_UNSET;
@@ -1895,7 +1881,7 @@ void filelist_clear_ex(FileList *filelist,
filelist_tag_needs_filtering(filelist);
if (do_cache) {
filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
filelist_cache_clear(filelist->filelist_cache, filelist->filelist_cache->size);
}
filelist_intern_free(filelist);
@@ -1931,7 +1917,7 @@ static void filelist_clear_main_files(FileList *filelist,
filelist_tag_needs_filtering(filelist);
if (do_cache) {
filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
filelist_cache_clear(filelist->filelist_cache, filelist->filelist_cache->size);
}
filelist->filelist.entries_num -= removed_files;
@@ -1975,7 +1961,7 @@ void filelist_free(FileList *filelist)
/* No need to clear cache & selection_state, we free them anyway. */
filelist_clear_ex(filelist, true, false, false);
filelist_cache_free(&filelist->filelist_cache);
MEM_delete(filelist->filelist_cache);
if (filelist->selection_state) {
BLI_ghash_free(filelist->selection_state, nullptr, nullptr);
@@ -2145,7 +2131,7 @@ int filelist_files_ensure(FileList *filelist)
static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int index)
{
FileListInternEntry *entry = filelist->filelist_intern.filtered[index];
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
FileDirEntry *ret;
ret = MEM_callocN<FileDirEntry>(__func__);
@@ -2188,7 +2174,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry)
{
BLI_remlink(&filelist->filelist_cache.cached_entries, entry);
BLI_remlink(&filelist->filelist_cache->cached_entries, entry);
filelist_entry_free(entry);
}
@@ -2208,7 +2194,7 @@ static FileDirEntry *filelist_cache_file_lookup(FileListEntryCache *cache, const
FileDirEntry *filelist_file_ex(FileList *filelist, const int index, const bool use_request)
{
FileDirEntry *ret = nullptr, *old;
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
int old_index;
if ((index < 0) || (index >= filelist->filelist.entries_filtered_num)) {
@@ -2353,8 +2339,8 @@ void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_siz
size *= 2;
}
if (size != filelist->filelist_cache.size) {
filelist_cache_clear(&filelist->filelist_cache, size);
if (size != filelist->filelist_cache->size) {
filelist_cache_clear(filelist->filelist_cache, size);
}
}
@@ -2364,7 +2350,7 @@ static bool filelist_file_cache_block_create(FileList *filelist,
const int size,
int cursor)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
int i, idx;
@@ -2385,7 +2371,7 @@ static bool filelist_file_cache_block_create(FileList *filelist,
static void filelist_file_cache_block_release(FileList *filelist, const int size, int cursor)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
int i;
@@ -2406,7 +2392,7 @@ static void filelist_file_cache_block_release(FileList *filelist, const int size
bool filelist_file_cache_block(FileList *filelist, const int index)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
const size_t cache_size = cache->size;
const int entries_num = filelist->filelist.entries_filtered_num;
@@ -2622,7 +2608,7 @@ bool filelist_file_cache_block(FileList *filelist, const int index)
void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
if (use_previews == ((cache->flags & FLC_PREVIEWS_ACTIVE) != 0)) {
return;
@@ -2647,7 +2633,7 @@ void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
bool filelist_cache_previews_update(FileList *filelist)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
TaskPool *pool = cache->previews_pool;
bool changed = false;
@@ -2705,14 +2691,14 @@ bool filelist_cache_previews_update(FileList *filelist)
bool filelist_cache_previews_running(FileList *filelist)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
return (cache->previews_pool != nullptr);
}
bool filelist_cache_previews_done(FileList *filelist)
{
FileListEntryCache *cache = &filelist->filelist_cache;
FileListEntryCache *cache = filelist->filelist_cache;
if ((cache->flags & FLC_PREVIEWS_ACTIVE) == 0) {
/* There are no previews. */
return false;
@@ -4135,7 +4121,7 @@ static void filelist_readjob_startjob(void *flrjv, wmJobWorkerStatus *worker_sta
}
flrj->tmp_filelist->libfiledata = nullptr;
memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
flrj->tmp_filelist->filelist_cache = nullptr;
flrj->tmp_filelist->selection_state = nullptr;
flrj->tmp_filelist->asset_library_ref = nullptr;
flrj->tmp_filelist->filter_data.asset_catalog_filter = nullptr;