[Bf-blender-cvs] [d85e94d] master: IMB_thumb: add thread locking API.

Bastien Montagne noreply at git.blender.org
Tue Aug 18 12:40:05 CEST 2015


Commit: d85e94da07d3d8bb213ef2e3d98c2032edad7155
Author: Bastien Montagne
Date:   Tue Aug 18 12:35:43 2015 +0200
Branches: master
https://developer.blender.org/rBd85e94da07d3d8bb213ef2e3d98c2032edad7155

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.

===================================================================

M	source/blender/imbuf/IMB_thumbs.h
M	source/blender/imbuf/intern/thumbs.c

===================================================================

diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h
index f2f7597..13237fe 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 1fb6c76..f67718f 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);
+}




More information about the Bf-blender-cvs mailing list