diff options
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r-- | source/blender/imbuf/IMB_thumbs.h | 6 | ||||
-rw-r--r-- | source/blender/imbuf/intern/thumbs.c | 76 |
2 files changed, 82 insertions, 0 deletions
diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index f2f75973bcd..13237fe26a1 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -91,6 +91,12 @@ void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y); bool IMB_thumb_load_font_get_hash(char *r_hash); +/* Threading */ +void IMB_thumb_locks_acquire(void); +void IMB_thumb_locks_release(void); +void IMB_thumb_path_lock(const char *path); +void IMB_thumb_path_unlock(const char *path); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 1fb6c7631b9..f67718ffcba 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -32,12 +32,16 @@ #include <stdio.h> #include <stdlib.h> +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_ghash.h" #include "BLI_hash_md5.h" #include "BLI_system.h" +#include "BLI_threads.h" #include BLI_SYSTEM_PID_H #include "IMB_imbuf_types.h" @@ -618,3 +622,75 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source return img; } + +/* ***** Threading ***** */ +/* Thumbnail handling is not really threadsafe in itself. + * However, as long as we do not operate on the same file, we shall have no collision. + * So idea is to 'lock' a given source file path. + */ + +static struct IMBThumbLocks { + GSet *locked_paths; + int lock_counter; + ThreadCondition cond; +} thumb_locks = {0}; + +void IMB_thumb_locks_acquire(void) { + BLI_lock_thread(LOCK_IMAGE); + + if (thumb_locks.lock_counter == 0) { + BLI_assert(thumb_locks.locked_paths == NULL); + thumb_locks.locked_paths = BLI_gset_str_new(__func__); + BLI_condition_init(&thumb_locks.cond); + } + thumb_locks.lock_counter++; + + BLI_assert(thumb_locks.locked_paths != NULL); + BLI_assert(thumb_locks.lock_counter > 0); + BLI_unlock_thread(LOCK_IMAGE); +} + +void IMB_thumb_locks_release(void) { + BLI_lock_thread(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + + thumb_locks.lock_counter--; + if (thumb_locks.lock_counter == 0) { + BLI_gset_free(thumb_locks.locked_paths, MEM_freeN); + thumb_locks.locked_paths = NULL; + BLI_condition_end(&thumb_locks.cond); + } + + BLI_unlock_thread(LOCK_IMAGE); +} + +void IMB_thumb_path_lock(const char *path) { + void *key = BLI_strdup(path); + + BLI_lock_thread(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + + if (thumb_locks.locked_paths) { + while (!BLI_gset_add(thumb_locks.locked_paths, key)) { + BLI_condition_wait_global_mutex(&thumb_locks.cond, LOCK_IMAGE); + } + } + + BLI_unlock_thread(LOCK_IMAGE); +} + +void IMB_thumb_path_unlock(const char *path) { + const void *key = path; + + BLI_lock_thread(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + + if (thumb_locks.locked_paths) { + if (!BLI_gset_remove(thumb_locks.locked_paths, key, MEM_freeN)) { + BLI_assert(0); + } + BLI_condition_notify_all(&thumb_locks.cond); + } + + BLI_unlock_thread(LOCK_IMAGE); +} |