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:
authorBastien Montagne <montagne29@wanadoo.fr>2015-08-18 13:35:43 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2015-08-18 13:39:45 +0300
commitd85e94da07d3d8bb213ef2e3d98c2032edad7155 (patch)
treee4a9993274bc4306170a86fe8f2c7b657de76e07
parent81afa2953cab20a59f1997aaf12dc85f5acbea0b (diff)
IMB_thumb: add thread locking API.
General idea is that, if several threads are handling thumbnails at the same time, they can end working on the same file at some point, which will generate conflict. To avoid this, threads can now lock a given filepath. Note that locking data is allocated on a ref-count basis, to avoid keeping the GSet in memory when not needed. Also, we are using global LOCK_IMAGE mutex for now. Needed for upcomming filebrowser rework.
-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);
+}