Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <mont29>2022-04-06 11:48:33 +0300
committerBastien Montagne <bastien@blender.org>2022-04-06 12:37:15 +0300
commite06399c223686aee7c2b6f9fb2db66a5f2cffad6 (patch)
tree15779f9dd3a1cdd312c16e96db7f924aa20606ae /source/blender/blenloader/intern/readfile.c
parent8dd3387eb74566f6c52d5c83f22a8e89a908df2a (diff)
Fix badly broken caches handling during undo/redo.
Original rework of caches during undo/redo (see D8183) had a very bad flaw hidden in it: using the key of a ghash as source of data. While this was effectively working then (cache pointer itself being part of the key, and said cache pointers not being cleared on file write), this is a general very bad way to do things. Now that cache pointers are more and more cleared on file write (as part of clearing runtime-data to reduce false-positives when checking if an ID has changed or not), this has to be fixed properly by: * Not storing the cache pointer itself in the IDCacheKey. * In undo context, in readfile code trying to preserve caches, store the cache pointers as values of the mapping, together with the usages counter The first change potentially affects all usages of `BKE_idtype_id_foreach_cache`, but in practice this code is only used by memfile reading code (i.e. undo) currently. Related to T97015. Reviewed By: brecht Maniphest Tasks: T97015 Differential Revision: https://developer.blender.org/D14559
Diffstat (limited to 'source/blender/blenloader/intern/readfile.c')
-rw-r--r--source/blender/blenloader/intern/readfile.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 4ea6287399c..aba0bfe84d2 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1689,12 +1689,14 @@ typedef struct BLOCacheStorage {
MemArena *memarena;
} BLOCacheStorage;
+typedef struct BLOCacheStorageValue {
+ void *cache_v;
+ uint new_usage_count;
+} BLOCacheStorageValue;
+
/** Register a cache data entry to be preserved when reading some undo memfile. */
-static void blo_cache_storage_entry_register(ID *id,
- const IDCacheKey *key,
- void **UNUSED(cache_p),
- uint UNUSED(flags),
- void *cache_storage_v)
+static void blo_cache_storage_entry_register(
+ ID *id, const IDCacheKey *key, void **cache_p, uint UNUSED(flags), void *cache_storage_v)
{
BLI_assert(key->id_session_uuid == id->session_uuid);
UNUSED_VARS_NDEBUG(id);
@@ -1704,7 +1706,11 @@ static void blo_cache_storage_entry_register(ID *id,
IDCacheKey *storage_key = BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_key));
*storage_key = *key;
- BLI_ghash_insert(cache_storage->cache_map, storage_key, POINTER_FROM_UINT(0));
+ BLOCacheStorageValue *storage_value = BLI_memarena_alloc(cache_storage->memarena,
+ sizeof(*storage_value));
+ storage_value->cache_v = *cache_p;
+ storage_value->new_usage_count = 0;
+ BLI_ghash_insert(cache_storage->cache_map, storage_key, storage_value);
}
/** Restore a cache data entry from old ID into new one, when reading some undo memfile. */
@@ -1723,13 +1729,13 @@ static void blo_cache_storage_entry_restore_in_new(
return;
}
- void **value = BLI_ghash_lookup_p(cache_storage->cache_map, key);
- if (value == NULL) {
+ BLOCacheStorageValue *storage_value = BLI_ghash_lookup(cache_storage->cache_map, key);
+ if (storage_value == NULL) {
*cache_p = NULL;
return;
}
- *value = POINTER_FROM_UINT(POINTER_AS_UINT(*value) + 1);
- *cache_p = key->cache_v;
+ storage_value->new_usage_count++;
+ *cache_p = storage_value->cache_v;
}
/** Clear as needed a cache data entry from old ID, when reading some undo memfile. */
@@ -1741,14 +1747,19 @@ static void blo_cache_storage_entry_clear_in_old(ID *UNUSED(id),
{
BLOCacheStorage *cache_storage = cache_storage_v;
- void **value = BLI_ghash_lookup_p(cache_storage->cache_map, key);
- if (value == NULL) {
+ BLOCacheStorageValue *storage_value = BLI_ghash_lookup(cache_storage->cache_map, key);
+ if (storage_value == NULL) {
*cache_p = NULL;
return;
}
/* If that cache has been restored into some new ID, we want to remove it from old one, otherwise
* keep it there so that it gets properly freed together with its ID. */
- *cache_p = POINTER_AS_UINT(*value) != 0 ? NULL : key->cache_v;
+ if (storage_value->new_usage_count != 0) {
+ *cache_p = NULL;
+ }
+ else {
+ BLI_assert(*cache_p == storage_value->cache_v);
+ }
}
void blo_cache_storage_init(FileData *fd, Main *bmain)