[Bf-blender-cvs] [c43725e1891] master: Add an session-wise uuid integer to IDs.

Bastien Montagne noreply at git.blender.org
Thu Mar 5 16:30:17 CET 2020


Commit: c43725e1891bd8534ac4b668277cddae9762d524
Author: Bastien Montagne
Date:   Thu Mar 5 16:17:14 2020 +0100
Branches: master
https://developer.blender.org/rBc43725e1891bd8534ac4b668277cddae9762d524

Add an session-wise uuid integer to IDs.

"session-wise" here mean while editing a same .blend file. So creating
or opening a new one will reset the uuid counter. This should avoid any
overflow in practice.

Only IDs added to Main database get an uuid, runtime-only ones are not
affected.

This is intended to provide undo with a way to find IDs across several
'memory realms' (undo speedup project).

No behavior change is expected from this commit itself.

Part of T60695.

Differential Revision: https://developer.blender.org/D7007

===================================================================

M	source/blender/blenkernel/BKE_lib_id.h
M	source/blender/blenkernel/BKE_main_idmap.h
M	source/blender/blenkernel/intern/lib_id.c
M	source/blender/blenkernel/intern/main_idmap.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/versioning_250.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/windowmanager/intern/wm_files.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index cb86d54009b..27dd1e637f3 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -67,6 +67,14 @@ void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const
     ATTR_WARN_UNUSED_RESULT;
 void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
 
+/* *** ID's session_uuid management. *** */
+
+/* When an ID's uuid is of that value, it is unset/invalid (e.g. for runtime IDs, etc.). */
+#define MAIN_ID_SESSION_UUID_UNSET 0
+
+void BKE_lib_libblock_session_uuid_reset(void);
+void BKE_lib_libblock_session_uuid_ensure(struct ID *id);
+
 void *BKE_id_new(struct Main *bmain, const short type, const char *name);
 void *BKE_id_new_nomain(const short type, const char *name);
 
diff --git a/source/blender/blenkernel/BKE_main_idmap.h b/source/blender/blenkernel/BKE_main_idmap.h
index a68d27a7882..e392b7db60e 100644
--- a/source/blender/blenkernel/BKE_main_idmap.h
+++ b/source/blender/blenkernel/BKE_main_idmap.h
@@ -40,22 +40,32 @@ struct ID;
 struct IDNameLib_Map;
 struct Main;
 
+enum {
+  MAIN_IDMAP_TYPE_NAME = 1 << 0,
+  MAIN_IDMAP_TYPE_UUID = 1 << 1,
+};
+
 struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
                                             const bool create_valid_ids_set,
-                                            struct Main *old_bmain) ATTR_WARN_UNUSED_RESULT
+                                            struct Main *old_bmain,
+                                            const int idmap_types) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL(1);
 void BKE_main_idmap_destroy(struct IDNameLib_Map *id_typemap) ATTR_NONNULL();
 struct Main *BKE_main_idmap_main_get(struct IDNameLib_Map *id_typemap) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
-struct ID *BKE_main_idmap_lookup(struct IDNameLib_Map *id_typemap,
-                                 short id_type,
-                                 const char *name,
-                                 const struct Library *lib) ATTR_WARN_UNUSED_RESULT
+struct ID *BKE_main_idmap_lookup_name(struct IDNameLib_Map *id_typemap,
+                                      short id_type,
+                                      const char *name,
+                                      const struct Library *lib) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL(1, 3);
 struct ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_typemap,
                                     const struct ID *id) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL(1, 2);
 
+struct ID *BKE_main_idmap_lookup_uuid(struct IDNameLib_Map *id_typemap,
+                                      const uint session_uuid) ATTR_WARN_UNUSED_RESULT
+    ATTR_NONNULL(1);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 416de844691..92e9a7c6c79 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1027,6 +1027,8 @@ void BKE_libblock_management_main_add(Main *bmain, void *idv)
   id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
   bmain->is_memfile_undo_written = false;
   BKE_main_unlock(bmain);
+
+  BKE_lib_libblock_session_uuid_ensure(id);
 }
 
 /** Remove a data-block from given main (set it to 'NO_MAIN' status). */
@@ -1313,6 +1315,8 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
       /* alphabetic insertion: is in new_id */
       BKE_main_unlock(bmain);
 
+      BKE_lib_libblock_session_uuid_ensure(id);
+
       /* TODO to be removed from here! */
       if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
         DEG_id_type_tag(bmain, type);
@@ -1456,6 +1460,33 @@ void BKE_libblock_init_empty(ID *id)
   }
 }
 
+/* ********** ID session-wise UUID management. ********** */
+static uint global_session_uuid = 0;
+
+/** Reset the session-wise uuid counter (used when reading a new file e.g.). */
+void BKE_lib_libblock_session_uuid_reset()
+{
+  global_session_uuid = 0;
+}
+
+/**
+ * Generate a session-wise uuid for the given \a id.
+ *
+ * \note "session-wise" here means while editing a given .blend file. Once a new .blend file is
+ * loaded or created, undo history is cleared/reset, and so is the uuid counter.
+ */
+void BKE_lib_libblock_session_uuid_ensure(ID *id)
+{
+  if (id->session_uuid == MAIN_ID_SESSION_UUID_UNSET) {
+    id->session_uuid = atomic_add_and_fetch_uint32(&global_session_uuid, 1);
+    /* In case overflow happens, still assign a valid ID. This way opening files many times works
+     * correctly. */
+    if (UNLIKELY(id->session_uuid == MAIN_ID_SESSION_UUID_UNSET)) {
+      id->session_uuid = atomic_add_and_fetch_uint32(&global_session_uuid, 1);
+    }
+  }
+}
+
 /**
  * Generic helper to create a new empty data-block of given type in given \a bmain database.
  *
diff --git a/source/blender/blenkernel/intern/main_idmap.c b/source/blender/blenkernel/intern/main_idmap.c
index a210961b212..26eb0b681a1 100644
--- a/source/blender/blenkernel/intern/main_idmap.c
+++ b/source/blender/blenkernel/intern/main_idmap.c
@@ -26,6 +26,7 @@
 #include "DNA_ID.h"
 
 #include "BKE_idcode.h"
+#include "BKE_lib_id.h"
 #include "BKE_main.h"
 #include "BKE_main_idmap.h" /* own include */
 
@@ -65,16 +66,20 @@ struct IDNameLib_TypeMap {
  */
 struct IDNameLib_Map {
   struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY];
+  struct GHash *uuid_map;
   struct Main *bmain;
   struct GSet *valid_id_pointers;
+  int idmap_types;
 };
 
 static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id_map,
                                                         short id_type)
 {
-  for (int i = 0; i < MAX_LIBARRAY; i++) {
-    if (id_map->type_maps[i].id_type == id_type) {
-      return &id_map->type_maps[i];
+  if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
+    for (int i = 0; i < MAX_LIBARRAY; i++) {
+      if (id_map->type_maps[i].id_type == id_type) {
+        return &id_map->type_maps[i];
+      }
     }
   }
   return NULL;
@@ -94,9 +99,12 @@ static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id
  */
 struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
                                             const bool create_valid_ids_set,
-                                            struct Main *old_bmain)
+                                            struct Main *old_bmain,
+                                            const int idmap_types)
 {
   struct IDNameLib_Map *id_map = MEM_mallocN(sizeof(*id_map), __func__);
+  id_map->bmain = bmain;
+  id_map->idmap_types = idmap_types;
 
   int index = 0;
   while (index < MAX_LIBARRAY) {
@@ -107,7 +115,22 @@ struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
   }
   BLI_assert(index == MAX_LIBARRAY);
 
-  id_map->bmain = bmain;
+  if (idmap_types & MAIN_IDMAP_TYPE_UUID) {
+    ID *id;
+    id_map->uuid_map = BLI_ghash_int_new(__func__);
+    FOREACH_MAIN_ID_BEGIN (bmain, id) {
+      BLI_assert(id->session_uuid != MAIN_ID_SESSION_UUID_UNSET);
+      void **id_ptr_v;
+      const bool existing_key = BLI_ghash_ensure_p(
+          id_map->uuid_map, POINTER_FROM_UINT(id->session_uuid), &id_ptr_v);
+      BLI_assert(existing_key == false);
+      *id_ptr_v = id;
+    }
+    FOREACH_MAIN_ID_END;
+  }
+  else {
+    id_map->uuid_map = NULL;
+  }
 
   if (create_valid_ids_set) {
     id_map->valid_id_pointers = BKE_main_gset_create(bmain, NULL);
@@ -144,10 +167,10 @@ static bool idkey_cmp(const void *a, const void *b)
   return strcmp(idkey_a->name, idkey_b->name) || (idkey_a->lib != idkey_b->lib);
 }
 
-ID *BKE_main_idmap_lookup(struct IDNameLib_Map *id_map,
-                          short id_type,
-                          const char *name,
-                          const Library *lib)
+ID *BKE_main_idmap_lookup_name(struct IDNameLib_Map *id_map,
+                               short id_type,
+                               const char *name,
+                               const Library *lib)
 {
   struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type);
 
@@ -188,21 +211,34 @@ ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_map, const ID *id)
    * when trying to get ID name).
    */
   if (id_map->valid_id_pointers == NULL || BLI_gset_haskey(id_map->valid_id_pointers, id)) {
-    return BKE_main_idmap_lookup(id_map, GS(id->name), id->name + 2, id->lib);
+    return BKE_main_idmap_lookup_name(id_map, GS(id->name), id->name + 2, id->lib);
+  }
+  return NULL;
+}
+
+ID *BKE_main_idmap_lookup_uuid(struct IDNameLib_Map *id_map, const uint session_uuid)
+{
+  if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) {
+    return BLI_ghash_lookup(id_map->uuid_map, POINTER_FROM_UINT(session_uuid));
   }
   return NULL;
 }
 
 void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map)
 {
-  struct IDNameLib_TypeMap *type_map = id_map->type_maps;
-  for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
-    if (type_map->map) {
-      BLI_ghash_free(type_map->map, NULL, NULL);
-      type_map->map = NULL;
-      MEM_freeN(type_map->keys);
+  if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
+    struct IDNameLib_TypeMap *type_map = id_map->type_maps;
+    for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
+      if (type_map->map) {
+        BLI_ghash_free(type_map->map, NULL, NULL);
+        type_map->map = NULL;
+        MEM_freeN(type_map->keys);
+      }
     }
   }
+  if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) {
+    BLI_ghash_free(id_map->uuid_map, NULL, NULL);
+  }
 
   if (id_map->valid_id_pointers != NULL) {
     BLI_gset_free(id_map->valid_id_pointers, NULL);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3107de38ff7..4d46435eea0 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8056,7 +8056,8 @@ void blo_lib_link_restore(Main *oldmain,
                           Scene *curscene,
                           ViewLayer *cur_view_layer)
 {
-  struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain, true, oldmain);
+  struct IDNameLib_Map *id_map = BKE_main_idmap_create(
+      n

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list