Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/main_idmap.c
| Show All 15 Lines | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_mempool.h" | |||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "DNA_ID.h" | #include "DNA_ID.h" | ||||
| #include "BKE_idtype.h" | #include "BKE_idtype.h" | ||||
| #include "BKE_lib_id.h" | #include "BKE_lib_id.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_main_idmap.h" /* own include */ | #include "BKE_main_idmap.h" /* own include */ | ||||
| Show All 21 Lines | struct IDNameLib_Key { | ||||
| const char *name; | const char *name; | ||||
| /** ``ID.lib``: */ | /** ``ID.lib``: */ | ||||
| const Library *lib; | const Library *lib; | ||||
| }; | }; | ||||
| struct IDNameLib_TypeMap { | struct IDNameLib_TypeMap { | ||||
| GHash *map; | GHash *map; | ||||
| short id_type; | short id_type; | ||||
| /* only for storage of keys in the ghash, avoid many single allocs */ | |||||
| struct IDNameLib_Key *keys; | |||||
| }; | }; | ||||
| /** | /** | ||||
| * Opaque structure, external API users only see this. | * Opaque structure, external API users only see this. | ||||
| */ | */ | ||||
| struct IDNameLib_Map { | struct IDNameLib_Map { | ||||
| struct IDNameLib_TypeMap type_maps[INDEX_ID_MAX]; | struct IDNameLib_TypeMap type_maps[INDEX_ID_MAX]; | ||||
| struct GHash *uuid_map; | struct GHash *uuid_map; | ||||
| struct Main *bmain; | struct Main *bmain; | ||||
| struct GSet *valid_id_pointers; | struct GSet *valid_id_pointers; | ||||
| int idmap_types; | int idmap_types; | ||||
| /* For storage of keys for the TypeMap ghash, avoids many single allocs. */ | |||||
| BLI_mempool *type_maps_keys_pool; | |||||
| }; | }; | ||||
| static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id_map, | static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id_map, | ||||
| short id_type) | short id_type) | ||||
| { | { | ||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { | if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { | ||||
| for (int i = 0; i < INDEX_ID_MAX; i++) { | for (int i = 0; i < INDEX_ID_MAX; i++) { | ||||
| if (id_map->type_maps[i].id_type == id_type) { | if (id_map->type_maps[i].id_type == id_type) { | ||||
| Show All 28 Lines | struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain, | ||||
| int index = 0; | int index = 0; | ||||
| while (index < INDEX_ID_MAX) { | while (index < INDEX_ID_MAX) { | ||||
| struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index]; | struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index]; | ||||
| type_map->map = NULL; | type_map->map = NULL; | ||||
| type_map->id_type = BKE_idtype_idcode_iter_step(&index); | type_map->id_type = BKE_idtype_idcode_iter_step(&index); | ||||
| BLI_assert(type_map->id_type != 0); | BLI_assert(type_map->id_type != 0); | ||||
| } | } | ||||
| BLI_assert(index == INDEX_ID_MAX); | BLI_assert(index == INDEX_ID_MAX); | ||||
| id_map->type_maps_keys_pool = NULL; | |||||
| if (idmap_types & MAIN_IDMAP_TYPE_UUID) { | if (idmap_types & MAIN_IDMAP_TYPE_UUID) { | ||||
| ID *id; | ID *id; | ||||
| id_map->uuid_map = BLI_ghash_int_new(__func__); | id_map->uuid_map = BLI_ghash_int_new(__func__); | ||||
| FOREACH_MAIN_ID_BEGIN (bmain, id) { | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| BLI_assert(id->session_uuid != MAIN_ID_SESSION_UUID_UNSET); | BLI_assert(id->session_uuid != MAIN_ID_SESSION_UUID_UNSET); | ||||
| void **id_ptr_v; | void **id_ptr_v; | ||||
| const bool existing_key = BLI_ghash_ensure_p( | const bool existing_key = BLI_ghash_ensure_p( | ||||
| Show All 17 Lines | struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain, | ||||
| } | } | ||||
| else { | else { | ||||
| id_map->valid_id_pointers = NULL; | id_map->valid_id_pointers = NULL; | ||||
| } | } | ||||
| return id_map; | return id_map; | ||||
| } | } | ||||
| void BKE_main_idmap_insert_id(struct IDNameLib_Map *id_map, ID *id) | |||||
| { | |||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { | |||||
| const short id_type = GS(id->name); | |||||
| struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type); | |||||
| /* No need to do anything if map has not been lazyly created yet. */ | |||||
| if (LIKELY(type_map != NULL) && type_map->map != NULL) { | |||||
| BLI_assert(id_map->type_maps_keys_pool != NULL); | |||||
| struct IDNameLib_Key *key = BLI_mempool_alloc(id_map->type_maps_keys_pool); | |||||
| key->name = id->name + 2; | |||||
| key->lib = id->lib; | |||||
| BLI_ghash_insert(type_map->map, key, id); | |||||
| } | |||||
| } | |||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) { | |||||
| BLI_assert(id_map->uuid_map != NULL); | |||||
| 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); | |||||
| UNUSED_VARS_NDEBUG(existing_key); | |||||
| *id_ptr_v = id; | |||||
| } | |||||
| } | |||||
| void BKE_main_idmap_remove_id(struct IDNameLib_Map *id_map, ID *id) | |||||
| { | |||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { | |||||
| const short id_type = GS(id->name); | |||||
| struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type); | |||||
| /* No need to do anything if map has not been lazyly created yet. */ | |||||
| if (LIKELY(type_map != NULL) && type_map->map != NULL) { | |||||
| BLI_assert(id_map->type_maps_keys_pool != NULL); | |||||
| /* NOTE: We cannot free the key from the MemPool here, would need new API from GHash to also | |||||
| * retrieve key pointer. Not a big deal for now */ | |||||
| BLI_ghash_remove(type_map->map, &(struct IDNameLib_Key){id->name + 2, id->lib}, NULL, NULL); | |||||
| } | |||||
| } | |||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) { | |||||
| BLI_assert(id_map->uuid_map != NULL); | |||||
| BLI_assert(id->session_uuid != MAIN_ID_SESSION_UUID_UNSET); | |||||
| BLI_ghash_remove(id_map->uuid_map, POINTER_FROM_UINT(id->session_uuid), NULL, NULL); | |||||
| } | |||||
| } | |||||
| struct Main *BKE_main_idmap_main_get(struct IDNameLib_Map *id_map) | struct Main *BKE_main_idmap_main_get(struct IDNameLib_Map *id_map) | ||||
| { | { | ||||
| return id_map->bmain; | return id_map->bmain; | ||||
| } | } | ||||
| static unsigned int idkey_hash(const void *ptr) | static unsigned int idkey_hash(const void *ptr) | ||||
| { | { | ||||
| const struct IDNameLib_Key *idkey = ptr; | const struct IDNameLib_Key *idkey = ptr; | ||||
| Show All 17 Lines | ID *BKE_main_idmap_lookup_name(struct IDNameLib_Map *id_map, | ||||
| const Library *lib) | const Library *lib) | ||||
| { | { | ||||
| struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type); | struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type); | ||||
| if (UNLIKELY(type_map == NULL)) { | if (UNLIKELY(type_map == NULL)) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* lazy init */ | /* Lazy init. */ | ||||
| if (type_map->map == NULL) { | if (type_map->map == NULL) { | ||||
| ListBase *lb = which_libbase(id_map->bmain, id_type); | if (id_map->type_maps_keys_pool == NULL) { | ||||
| const int lb_len = BLI_listbase_count(lb); | id_map->type_maps_keys_pool = BLI_mempool_create( | ||||
| if (lb_len == 0) { | sizeof(struct IDNameLib_Key), 1024, 1024, BLI_MEMPOOL_NOP); | ||||
| return NULL; | |||||
| } | } | ||||
| type_map->map = BLI_ghash_new_ex(idkey_hash, idkey_cmp, __func__, lb_len); | |||||
| type_map->keys = MEM_mallocN(sizeof(struct IDNameLib_Key) * lb_len, __func__); | |||||
| GHash *map = type_map->map; | |||||
| struct IDNameLib_Key *key = type_map->keys; | |||||
| for (ID *id = lb->first; id; id = id->next, key++) { | GHash *map = type_map->map = BLI_ghash_new(idkey_hash, idkey_cmp, __func__); | ||||
| ListBase *lb = which_libbase(id_map->bmain, id_type); | |||||
| for (ID *id = lb->first; id; id = id->next) { | |||||
| struct IDNameLib_Key *key = BLI_mempool_alloc(id_map->type_maps_keys_pool); | |||||
| key->name = id->name + 2; | key->name = id->name + 2; | ||||
| key->lib = id->lib; | key->lib = id->lib; | ||||
| BLI_ghash_insert(map, key, id); | BLI_ghash_insert(map, key, id); | ||||
| } | } | ||||
| } | } | ||||
| const struct IDNameLib_Key key_lookup = {name, lib}; | const struct IDNameLib_Key key_lookup = {name, lib}; | ||||
| return BLI_ghash_lookup(type_map->map, &key_lookup); | return BLI_ghash_lookup(type_map->map, &key_lookup); | ||||
| Show All 24 Lines | |||||
| void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map) | void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map) | ||||
| { | { | ||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { | if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) { | ||||
| struct IDNameLib_TypeMap *type_map = id_map->type_maps; | struct IDNameLib_TypeMap *type_map = id_map->type_maps; | ||||
| for (int i = 0; i < INDEX_ID_MAX; i++, type_map++) { | for (int i = 0; i < INDEX_ID_MAX; i++, type_map++) { | ||||
| if (type_map->map) { | if (type_map->map) { | ||||
| BLI_ghash_free(type_map->map, NULL, NULL); | BLI_ghash_free(type_map->map, NULL, NULL); | ||||
| type_map->map = NULL; | type_map->map = NULL; | ||||
| MEM_freeN(type_map->keys); | |||||
| } | } | ||||
| } | } | ||||
| if (id_map->type_maps_keys_pool != NULL) { | |||||
| BLI_mempool_destroy(id_map->type_maps_keys_pool); | |||||
| id_map->type_maps_keys_pool = NULL; | |||||
| } | |||||
| } | } | ||||
| if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) { | if (id_map->idmap_types & MAIN_IDMAP_TYPE_UUID) { | ||||
| BLI_ghash_free(id_map->uuid_map, NULL, NULL); | BLI_ghash_free(id_map->uuid_map, NULL, NULL); | ||||
| } | } | ||||
| BLI_assert(id_map->type_maps_keys_pool == NULL); | |||||
| if (id_map->valid_id_pointers != NULL) { | if (id_map->valid_id_pointers != NULL) { | ||||
| BLI_gset_free(id_map->valid_id_pointers, NULL); | BLI_gset_free(id_map->valid_id_pointers, NULL); | ||||
| } | } | ||||
| MEM_freeN(id_map); | MEM_freeN(id_map); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||