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 /source/blender/imbuf/intern/thumbs.c
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.
Diffstat (limited to 'source/blender/imbuf/intern/thumbs.c')
-rw-r--r--source/blender/imbuf/intern/thumbs.c76
1 files changed, 76 insertions, 0 deletions
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);
+}