Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/imbuf/IMB_thumbs.h6
-rw-r--r--source/blender/imbuf/intern/thumbs.c76
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);
+}