Cleanup: move weak reference map to C++

This replaces a `GHash` with `Map<LibWeakRefKey, ID *>` which simplifies the code.

Pull Request: https://projects.blender.org/blender/blender/pulls/124519
This commit is contained in:
Jacques Lucke
2024-07-11 18:43:35 +02:00
parent 6ace3eb065
commit 436f4570c2
3 changed files with 84 additions and 90 deletions

View File

@@ -382,17 +382,20 @@ GSet *BKE_main_gset_create(Main *bmain, GSet *gset);
/* Temporary runtime API to allow re-using local (already appended)
* IDs instead of appending a new copy again. */
struct MainLibraryWeakReferenceMap;
/**
* Generate a mapping between 'library path' of an ID
* (as a pair (relative blend file path, id name)), and a current local ID, if any.
*
* This uses the information stored in `ID.library_weak_reference`.
*/
GHash *BKE_main_library_weak_reference_create(Main *bmain) ATTR_NONNULL();
MainLibraryWeakReferenceMap *BKE_main_library_weak_reference_create(Main *bmain) ATTR_NONNULL();
/**
* Destroy the data generated by #BKE_main_library_weak_reference_create.
*/
void BKE_main_library_weak_reference_destroy(GHash *library_weak_reference_mapping) ATTR_NONNULL();
void BKE_main_library_weak_reference_destroy(
MainLibraryWeakReferenceMap *library_weak_reference_mapping) ATTR_NONNULL();
/**
* Search for a local ID matching the given linked ID reference.
*
@@ -402,9 +405,10 @@ void BKE_main_library_weak_reference_destroy(GHash *library_weak_reference_mappi
* \param library_id_name: the full ID name, including the leading two chars encoding the ID
* type.
*/
ID *BKE_main_library_weak_reference_search_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name) ATTR_NONNULL();
ID *BKE_main_library_weak_reference_search_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name) ATTR_NONNULL();
/**
* Add the given ID weak library reference to given local ID and the runtime mapping.
*
@@ -414,10 +418,11 @@ ID *BKE_main_library_weak_reference_search_item(GHash *library_weak_reference_ma
* \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
* \param new_id: New local ID matching given weak reference.
*/
void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *new_id) ATTR_NONNULL();
void BKE_main_library_weak_reference_add_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *new_id) ATTR_NONNULL();
/**
* Update the status of the given ID weak library reference in current local IDs and the runtime
* mapping.
@@ -432,11 +437,12 @@ void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapp
* \param old_id: Existing local ID matching given weak reference.
* \param new_id: New local ID matching given weak reference.
*/
void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id,
ID *new_id) ATTR_NONNULL();
void BKE_main_library_weak_reference_update_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id,
ID *new_id) ATTR_NONNULL();
/**
* Remove the given ID weak library reference from the given local ID and the runtime mapping.
*
@@ -446,10 +452,11 @@ void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_m
* \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
* \param old_id: Existing local ID matching given weak reference.
*/
void BKE_main_library_weak_reference_remove_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id) ATTR_NONNULL();
void BKE_main_library_weak_reference_remove_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id) ATTR_NONNULL();
/* *** Generic utils to loop over whole Main database. *** */

View File

@@ -121,7 +121,7 @@ struct BlendfileLinkAppendContext {
blender::Map<ID *, BlendfileLinkAppendContextItem *> new_id_to_item;
/** Runtime info used by append code to manage re-use of already appended matching IDs. */
GHash *library_weak_reference_mapping = nullptr;
MainLibraryWeakReferenceMap *library_weak_reference_mapping = nullptr;
/** Embedded blendfile and its size, if needed. */
const void *blendfile_mem = nullptr;

View File

@@ -630,40 +630,32 @@ GSet *BKE_main_gset_create(Main *bmain, GSet *gset)
struct LibWeakRefKey {
char filepath[FILE_MAX];
char id_name[MAX_ID_NAME];
LibWeakRefKey(const char *lib_path, const char *id_name)
{
STRNCPY(this->filepath, lib_path);
STRNCPY(this->id_name, id_name);
}
friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
{
return STREQ(a.filepath, b.filepath) && STREQ(a.id_name, b.id_name);
}
uint64_t hash() const
{
return blender::get_default_hash(blender::StringRef(this->filepath),
blender::StringRef(this->id_name));
}
};
static LibWeakRefKey *lib_weak_key_create(LibWeakRefKey *key,
const char *lib_path,
const char *id_name)
{
if (key == nullptr) {
key = static_cast<LibWeakRefKey *>(MEM_mallocN(sizeof(*key), __func__));
}
STRNCPY(key->filepath, lib_path);
STRNCPY(key->id_name, id_name);
return key;
}
struct MainLibraryWeakReferenceMap {
blender::Map<LibWeakRefKey, ID *> map;
};
static uint lib_weak_key_hash(const void *ptr)
MainLibraryWeakReferenceMap *BKE_main_library_weak_reference_create(Main *bmain)
{
const LibWeakRefKey *string_pair = static_cast<const LibWeakRefKey *>(ptr);
uint hash = BLI_ghashutil_strhash_p_murmur(string_pair->filepath);
return hash ^ BLI_ghashutil_strhash_p_murmur(string_pair->id_name);
}
static bool lib_weak_key_cmp(const void *a, const void *b)
{
const LibWeakRefKey *string_pair_a = static_cast<const LibWeakRefKey *>(a);
const LibWeakRefKey *string_pair_b = static_cast<const LibWeakRefKey *>(b);
return !(STREQ(string_pair_a->filepath, string_pair_b->filepath) &&
STREQ(string_pair_a->id_name, string_pair_b->id_name));
}
GHash *BKE_main_library_weak_reference_create(Main *bmain)
{
GHash *library_weak_reference_mapping = BLI_ghash_new(
lib_weak_key_hash, lib_weak_key_cmp, __func__);
auto *library_weak_reference_mapping = MEM_new<MainLibraryWeakReferenceMap>(__func__);
ListBase *lb;
FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
@@ -680,10 +672,9 @@ GHash *BKE_main_library_weak_reference_create(Main *bmain)
if (id_iter->library_weak_reference == nullptr) {
continue;
}
LibWeakRefKey *key = lib_weak_key_create(nullptr,
id_iter->library_weak_reference->library_filepath,
id_iter->library_weak_reference->library_id_name);
BLI_ghash_insert(library_weak_reference_mapping, key, id_iter);
const LibWeakRefKey key{id_iter->library_weak_reference->library_filepath,
id_iter->library_weak_reference->library_id_name};
library_weak_reference_mapping->map.add(key, id_iter);
}
FOREACH_MAIN_LISTBASE_ID_END;
}
@@ -692,24 +683,26 @@ GHash *BKE_main_library_weak_reference_create(Main *bmain)
return library_weak_reference_mapping;
}
void BKE_main_library_weak_reference_destroy(GHash *library_weak_reference_mapping)
void BKE_main_library_weak_reference_destroy(
MainLibraryWeakReferenceMap *library_weak_reference_mapping)
{
BLI_ghash_free(library_weak_reference_mapping, MEM_freeN, nullptr);
MEM_delete(library_weak_reference_mapping);
}
ID *BKE_main_library_weak_reference_search_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name)
ID *BKE_main_library_weak_reference_search_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name)
{
LibWeakRefKey key;
lib_weak_key_create(&key, library_filepath, library_id_name);
return (ID *)BLI_ghash_lookup(library_weak_reference_mapping, &key);
const LibWeakRefKey key{library_filepath, library_id_name};
return library_weak_reference_mapping->map.lookup_default(key, nullptr);
}
void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *new_id)
void BKE_main_library_weak_reference_add_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *new_id)
{
BLI_assert(GS(library_id_name) == GS(new_id->name));
BLI_assert(new_id->library_weak_reference == nullptr);
@@ -718,23 +711,19 @@ void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapp
new_id->library_weak_reference = static_cast<LibraryWeakReference *>(
MEM_mallocN(sizeof(*(new_id->library_weak_reference)), __func__));
LibWeakRefKey *key = lib_weak_key_create(nullptr, library_filepath, library_id_name);
void **id_p;
const bool already_exist_in_mapping = BLI_ghash_ensure_p(
library_weak_reference_mapping, key, &id_p);
BLI_assert(!already_exist_in_mapping);
UNUSED_VARS_NDEBUG(already_exist_in_mapping);
const LibWeakRefKey key{library_filepath, library_id_name};
library_weak_reference_mapping->map.add_new(key, new_id);
STRNCPY(new_id->library_weak_reference->library_filepath, library_filepath);
STRNCPY(new_id->library_weak_reference->library_id_name, library_id_name);
*id_p = new_id;
}
void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id,
ID *new_id)
void BKE_main_library_weak_reference_update_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id,
ID *new_id)
{
BLI_assert(GS(library_id_name) == GS(old_id->name));
BLI_assert(GS(library_id_name) == GS(new_id->name));
@@ -743,29 +732,27 @@ void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_m
BLI_assert(STREQ(old_id->library_weak_reference->library_filepath, library_filepath));
BLI_assert(STREQ(old_id->library_weak_reference->library_id_name, library_id_name));
LibWeakRefKey key;
lib_weak_key_create(&key, library_filepath, library_id_name);
void **id_p = BLI_ghash_lookup_p(library_weak_reference_mapping, &key);
BLI_assert(id_p != nullptr && *id_p == old_id);
const LibWeakRefKey key{library_filepath, library_id_name};
BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
library_weak_reference_mapping->map.add_overwrite(key, new_id);
new_id->library_weak_reference = old_id->library_weak_reference;
old_id->library_weak_reference = nullptr;
*id_p = new_id;
}
void BKE_main_library_weak_reference_remove_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id)
void BKE_main_library_weak_reference_remove_item(
MainLibraryWeakReferenceMap *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
ID *old_id)
{
BLI_assert(GS(library_id_name) == GS(old_id->name));
BLI_assert(old_id->library_weak_reference != nullptr);
LibWeakRefKey key;
lib_weak_key_create(&key, library_filepath, library_id_name);
const LibWeakRefKey key{library_filepath, library_id_name};
BLI_assert(BLI_ghash_lookup(library_weak_reference_mapping, &key) == old_id);
BLI_ghash_remove(library_weak_reference_mapping, &key, MEM_freeN, nullptr);
BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
library_weak_reference_mapping->map.remove(key);
MEM_SAFE_FREE(old_id->library_weak_reference);
}