diff options
Diffstat (limited to 'source/blender/blenkernel/intern/icons.c')
-rw-r--r-- | source/blender/blenkernel/intern/icons.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 7302d62d20f..6aa00b2c97d 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -48,7 +48,9 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" +#include "BLI_linklist_lockfree.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BKE_icons.h" #include "BKE_global.h" /* only for G.background test */ @@ -71,6 +73,13 @@ static int gFirstIconId = 1; static GHash *gCachedPreviews = NULL; +/* Queue of icons for deferred deletion. */ +typedef struct DeferredIconDeleteNode { + struct DeferredIconDeleteNode *next; + int icon_id; +} DeferredIconDeleteNode; +static LockfreeLinkList g_icon_delete_queue; + static void icon_free(void *val) { Icon *icon = val; @@ -90,6 +99,7 @@ static void icon_free(void *val) * after the integer number range is used up */ static int get_next_free_id(void) { + BLI_assert(BLI_thread_is_main()); int startId = gFirstIconId; /* if we haven't used up the int number range, we just return the next int */ @@ -110,11 +120,15 @@ static int get_next_free_id(void) void BKE_icons_init(int first_dyn_id) { + BLI_assert(BLI_thread_is_main()); + gNextIconId = first_dyn_id; gFirstIconId = first_dyn_id; - if (!gIcons) + if (!gIcons) { gIcons = BLI_ghash_int_new(__func__); + BLI_linklist_lockfree_init(&g_icon_delete_queue); + } if (!gCachedPreviews) { gCachedPreviews = BLI_ghash_str_new(__func__); @@ -123,6 +137,8 @@ void BKE_icons_init(int first_dyn_id) void BKE_icons_free(void) { + BLI_assert(BLI_thread_is_main()); + if (gIcons) { BLI_ghash_free(gIcons, NULL, icon_free); gIcons = NULL; @@ -132,6 +148,22 @@ void BKE_icons_free(void) BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc); gCachedPreviews = NULL; } + + BLI_linklist_lockfree_free(&g_icon_delete_queue, MEM_freeN); +} + +void BKE_icons_deferred_free(void) +{ + BLI_assert(BLI_thread_is_main()); + + for (DeferredIconDeleteNode *node = + (DeferredIconDeleteNode *)BLI_linklist_lockfree_begin(&g_icon_delete_queue); + node != NULL; + node = node->next) + { + BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(node->icon_id), NULL, icon_free); + } + BLI_linklist_lockfree_clear(&g_icon_delete_queue, MEM_freeN); } static PreviewImage *previewimg_create_ex(size_t deferred_data_size) @@ -433,6 +465,8 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size) void BKE_icon_changed(const int icon_id) { + BLI_assert(BLI_thread_is_main()); + Icon *icon = NULL; if (!icon_id || G.background) return; @@ -460,6 +494,8 @@ void BKE_icon_changed(const int icon_id) static int icon_id_ensure_create_icon(struct ID *id) { + BLI_assert(BLI_thread_is_main()); + Icon *new_icon = NULL; new_icon = MEM_mallocN(sizeof(Icon), __func__); @@ -554,6 +590,8 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) Icon *BKE_icon_get(const int icon_id) { + BLI_assert(BLI_thread_is_main()); + Icon *icon = NULL; icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id)); @@ -568,6 +606,8 @@ Icon *BKE_icon_get(const int icon_id) void BKE_icon_set(const int icon_id, struct Icon *icon) { + BLI_assert(BLI_thread_is_main()); + void **val_p; if (BLI_ghash_ensure_p(gIcons, SET_INT_IN_POINTER(icon_id), &val_p)) { @@ -578,12 +618,28 @@ void BKE_icon_set(const int icon_id, struct Icon *icon) *val_p = icon; } -void BKE_icon_id_delete(struct ID *id) +static void icon_add_to_deferred_delete_queue(int icon_id) { - if (!id->icon_id) return; /* no icon defined for library object */ + DeferredIconDeleteNode *node = + MEM_mallocN(sizeof(DeferredIconDeleteNode), __func__); + node->icon_id = icon_id; + BLI_linklist_lockfree_insert(&g_icon_delete_queue, + (LockfreeLinkNode *)node); +} - BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), NULL, icon_free); +void BKE_icon_id_delete(struct ID *id) +{ + const int icon_id = id->icon_id; + if (!icon_id) return; /* no icon defined for library object */ id->icon_id = 0; + + if (!BLI_thread_is_main()) { + icon_add_to_deferred_delete_queue(icon_id); + return; + } + + BKE_icons_deferred_free(); + BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(icon_id), NULL, icon_free); } /** |