[Bf-blender-cvs] [7d7e90ca685] master: UI: Use vector instead of linked lists for context store
Hans Goudey
noreply at git.blender.org
Mon Dec 19 06:24:20 CET 2022
Commit: 7d7e90ca685954409ece007d03d2e93860a6cef7
Author: Hans Goudey
Date: Sun Dec 18 19:13:15 2022 -0600
Branches: master
https://developer.blender.org/rB7d7e90ca685954409ece007d03d2e93860a6cef7
UI: Use vector instead of linked lists for context store
Duplicating context lists took a measurable amount of time when drawing
large node trees in the node editor. Instead of using a linked list of
entries, which results in many small allocations, use a vector. Also,
use std::string and StringRefNull instead of char buffers and pointers.
===================================================================
M source/blender/blenkernel/BKE_context.h
M source/blender/blenkernel/intern/context.cc
M source/blender/editors/interface/interface.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 90597a3e273..f836b98f3b2 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -16,6 +16,11 @@
#include "DNA_object_enums.h"
#include "RNA_types.h"
+#ifdef __cplusplus
+# include "BLI_string_ref.hh"
+# include "BLI_vector.hh"
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -84,19 +89,22 @@ typedef int /*eContextResult*/ (*bContextDataCallback)(const bContext *C,
const char *member,
bContextDataResult *result);
-typedef struct bContextStoreEntry {
- struct bContextStoreEntry *next, *prev;
+#ifdef __cplusplus
- char name[128];
+struct bContextStoreEntry {
+ std::string name;
PointerRNA ptr;
-} bContextStoreEntry;
+};
+
+struct bContextStore {
+ bContextStore *next = nullptr;
+ bContextStore *prev = nullptr;
-typedef struct bContextStore {
- struct bContextStore *next, *prev;
+ blender::Vector<bContextStoreEntry> entries;
+ bool used = false;
+};
- ListBase entries;
- bool used;
-} bContextStore;
+#endif
/* for the context's rna mode enum
* keep aligned with data_mode_strings in context.cc */
@@ -132,18 +140,23 @@ void CTX_free(bContext *C);
bContext *CTX_copy(const bContext *C);
+#ifdef __cplusplus
+
/* Stored Context */
-bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr);
+bContextStore *CTX_store_add(ListBase *contexts,
+ blender::StringRefNull name,
+ const PointerRNA *ptr);
bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context);
bContextStore *CTX_store_get(bContext *C);
void CTX_store_set(bContext *C, bContextStore *store);
const PointerRNA *CTX_store_ptr_lookup(const bContextStore *store,
- const char *name,
- const StructRNA *type CPP_ARG_DEFAULT(nullptr));
-bContextStore *CTX_store_copy(bContextStore *store);
+ blender::StringRefNull name,
+ const StructRNA *type = nullptr);
+bContextStore *CTX_store_copy(const bContextStore *store);
void CTX_store_free(bContextStore *store);
-void CTX_store_free_list(ListBase *contexts);
+
+#endif
/* need to store if python is initialized or not */
bool CTX_py_init_get(bContext *C);
diff --git a/source/blender/blenkernel/intern/context.cc b/source/blender/blenkernel/intern/context.cc
index 4469f22346a..8d8e96f26c8 100644
--- a/source/blender/blenkernel/intern/context.cc
+++ b/source/blender/blenkernel/intern/context.cc
@@ -126,7 +126,9 @@ void CTX_free(bContext *C)
/* store */
-bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr)
+bContextStore *CTX_store_add(ListBase *contexts,
+ const blender::StringRefNull name,
+ const PointerRNA *ptr)
{
/* ensure we have a context to put the entry in, if it was already used
* we have to copy the context to ensure */
@@ -134,23 +136,16 @@ bContextStore *CTX_store_add(ListBase *contexts, const char *name, const Pointer
if (!ctx || ctx->used) {
if (ctx) {
- bContextStore *lastctx = ctx;
- ctx = MEM_new<bContextStore>(__func__);
- *ctx = *lastctx;
- BLI_duplicatelist(&ctx->entries, &lastctx->entries);
+ ctx = MEM_new<bContextStore>(__func__, *ctx);
}
else {
- ctx = MEM_cnew<bContextStore>(__func__);
+ ctx = MEM_new<bContextStore>(__func__);
}
BLI_addtail(contexts, ctx);
}
- bContextStoreEntry *entry = MEM_cnew<bContextStoreEntry>(__func__);
- BLI_strncpy(entry->name, name, sizeof(entry->name));
- entry->ptr = *ptr;
-
- BLI_addtail(&ctx->entries, entry);
+ ctx->entries.append(bContextStoreEntry{name, *ptr});
return ctx;
}
@@ -163,22 +158,17 @@ bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
if (!ctx || ctx->used) {
if (ctx) {
- bContextStore *lastctx = ctx;
- ctx = MEM_new<bContextStore>(__func__);
- *ctx = *lastctx;
- BLI_duplicatelist(&ctx->entries, &lastctx->entries);
+ ctx = MEM_new<bContextStore>(__func__, *ctx);
}
else {
- ctx = MEM_cnew<bContextStore>(__func__);
+ ctx = MEM_new<bContextStore>(__func__);
}
BLI_addtail(contexts, ctx);
}
- LISTBASE_FOREACH (bContextStoreEntry *, tentry, &context->entries) {
- bContextStoreEntry *entry = MEM_cnew<bContextStoreEntry>(__func__);
- *entry = *tentry;
- BLI_addtail(&ctx->entries, entry);
+ for (const bContextStoreEntry &src_entry : context->entries) {
+ ctx->entries.append(src_entry);
}
return ctx;
@@ -195,42 +185,27 @@ void CTX_store_set(bContext *C, bContextStore *store)
}
const PointerRNA *CTX_store_ptr_lookup(const bContextStore *store,
- const char *name,
+ const blender::StringRefNull name,
const StructRNA *type)
{
- bContextStoreEntry *entry = static_cast<bContextStoreEntry *>(
- BLI_rfindstring(&store->entries, name, offsetof(bContextStoreEntry, name)));
- if (!entry) {
- return nullptr;
- }
-
- if (type && !RNA_struct_is_a(entry->ptr.type, type)) {
- return nullptr;
+ for (auto entry = store->entries.rbegin(); entry != store->entries.rend(); ++entry) {
+ if (entry->name == name) {
+ if (type && RNA_struct_is_a(entry->ptr.type, type)) {
+ return &entry->ptr;
+ }
+ }
}
- return &entry->ptr;
+ return nullptr;
}
-bContextStore *CTX_store_copy(bContextStore *store)
+bContextStore *CTX_store_copy(const bContextStore *store)
{
- bContextStore *ctx = MEM_cnew<bContextStore>(__func__);
- *ctx = *store;
- BLI_duplicatelist(&ctx->entries, &store->entries);
-
- return ctx;
+ return MEM_new<bContextStore>(__func__, *store);
}
void CTX_store_free(bContextStore *store)
{
- BLI_freelistN(&store->entries);
- MEM_freeN(store);
-}
-
-void CTX_store_free_list(ListBase *contexts)
-{
- bContextStore *ctx;
- while ((ctx = static_cast<bContextStore *>(BLI_pophead(contexts)))) {
- CTX_store_free(ctx);
- }
+ MEM_delete(store);
}
/* is python initialized? */
@@ -592,11 +567,8 @@ ListBase CTX_data_dir_get_ex(const bContext *C,
RNA_PROP_END;
}
if (use_store && C->wm.store) {
- bContextStoreEntry *entry;
-
- for (entry = static_cast<bContextStoreEntry *>(C->wm.store->entries.first); entry;
- entry = entry->next) {
- data_dir_add(&lb, entry->name, use_all);
+ for (const bContextStoreEntry &entry : C->wm.store->entries) {
+ data_dir_add(&lb, entry.name.c_str(), use_all);
}
}
if ((region = CTX_wm_region(C)) && region->type && region->type->context) {
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 4d423f989a6..c16c3068320 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -3470,7 +3470,9 @@ void UI_block_free(const bContext *C, uiBlock *block)
MEM_freeN(block->func_argN);
}
- CTX_store_free_list(&block->contexts);
+ LISTBASE_FOREACH_MUTABLE (bContextStore *, store, &block->contexts) {
+ CTX_store_free(store);
+ }
BLI_freelistN(&block->saferct);
BLI_freelistN(&block->color_pickers.list);
More information about the Bf-blender-cvs
mailing list