[Bf-blender-cvs] [2291e60] new-filebrowser-preview-temp: Address Brecht's review, mainly:

Bastien Montagne noreply at git.blender.org
Sun Oct 18 18:33:08 CEST 2015


Commit: 2291e6015d346d10772a3773e2bd1c7f573f8510
Author: Bastien Montagne
Date:   Sun Oct 18 18:28:13 2015 +0200
Branches: new-filebrowser-preview-temp
https://developer.blender.org/rB2291e6015d346d10772a3773e2bd1c7f573f8510

Address Brecht's review, mainly:

* Simplifies handling of 'background fallback thread' in scheduler
* Add note (and debug check) that background pools do not get created recursively (from other task pools).

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

M	source/blender/blenlib/intern/task.c

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

diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index abd4435..b5715e0 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -63,14 +63,15 @@ struct TaskPool {
 	volatile bool do_cancel;
 
 	/* If set, this pool may never be work_and_wait'ed, which means TaskScheduler has to use its special
-	 * background fallback thread in case we are in mono-threaded situation. */
-	bool use_force_background;
+	 * background fallback thread in case we are in single-threaded situation. */
+	bool run_in_background;
 };
 
 struct TaskScheduler {
 	pthread_t *threads;
 	struct TaskThread *task_threads;
 	int num_threads;
+	bool background_thread_only;
 
 	ListBase queue;
 	ThreadMutex queue_mutex;
@@ -125,7 +126,7 @@ static void task_pool_num_increase(TaskPool *pool)
 	BLI_mutex_unlock(&pool->num_mutex);
 }
 
-static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task, const bool forced_background)
+static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
 {
 	bool found_task = false;
 	BLI_mutex_lock(&scheduler->queue_mutex);
@@ -146,7 +147,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
 		{
 			TaskPool *pool = current_task->pool;
 
-			if (forced_background && !pool->use_force_background) {
+			if (scheduler->background_thread_only && !pool->run_in_background) {
 				continue;
 			}
 
@@ -169,7 +170,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
 	return true;
 }
 
-static void *task_scheduler_thread_run_ex(void *thread_p, const bool forced_background)
+static void *task_scheduler_thread_run(void *thread_p)
 {
 	TaskThread *thread = (TaskThread *) thread_p;
 	TaskScheduler *scheduler = thread->scheduler;
@@ -177,7 +178,7 @@ static void *task_scheduler_thread_run_ex(void *thread_p, const bool forced_back
 	Task *task;
 
 	/* keep popping off tasks */
-	while (task_scheduler_thread_wait_pop(scheduler, &task, forced_background)) {
+	while (task_scheduler_thread_wait_pop(scheduler, &task)) {
 		TaskPool *pool = task->pool;
 
 		/* run task */
@@ -194,16 +195,6 @@ static void *task_scheduler_thread_run_ex(void *thread_p, const bool forced_back
 	return NULL;
 }
 
-static void *task_scheduler_thread_run(void *thread_p)
-{
-	return task_scheduler_thread_run_ex(thread_p, false);
-}
-
-static void *task_scheduler_thread_run_forced_background(void *thread_p)
-{
-	return task_scheduler_thread_run_ex(thread_p, true);
-}
-
 TaskScheduler *BLI_task_scheduler_create(int num_threads)
 {
 	TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler");
@@ -224,6 +215,12 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
 	/* main thread will also work, so we count it too */
 	num_threads -= 1;
 
+	/* Add background-only thread if needed. */
+	if (num_threads == 0) {
+	    scheduler->background_thread_only = true;
+	    num_threads = 1;
+	}
+
 	/* launch threads that will be waiting for work */
 	if (num_threads > 0) {
 		int i;
@@ -242,21 +239,6 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
 			}
 		}
 	}
-	else {
-		/* We create a thread, but only for pools that are 'forced background'. */
-		TaskThread *thread;
-
-		scheduler->num_threads = 1;
-		scheduler->threads = MEM_callocN(sizeof(pthread_t), "TaskScheduler threads");
-		thread = scheduler->task_threads = MEM_callocN(sizeof(TaskThread), "TaskScheduler task threads");
-
-		thread->scheduler = scheduler;
-		thread->id = 1;
-
-		if (pthread_create(&scheduler->threads[0], NULL, task_scheduler_thread_run_forced_background, thread) != 0) {
-			fprintf(stderr, "TaskScheduler failed to launch forced background thread\n");
-		}
-	}
 
 	return scheduler;
 }
@@ -353,12 +335,24 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, c
 {
 	TaskPool *pool = MEM_callocN(sizeof(TaskPool), "TaskPool");
 
+#ifndef NDEBUG
+	/* Assert we do not try to create a background pool from some parent task - those only work OK from main thread. */
+	if (is_background) {
+		const pthread_t thread_id = pthread_self();
+        int i = scheduler->num_threads;
+
+		while (i--) {
+			BLI_assert(scheduler->threads[i] != thread_id);
+		}
+	}
+#endif
+
 	pool->scheduler = scheduler;
 	pool->num = 0;
 	pool->num_threads = 0;
 	pool->currently_running_tasks = 0;
 	pool->do_cancel = false;
-	pool->use_force_background = is_background;
+	pool->run_in_background = is_background;
 
 	BLI_mutex_init(&pool->num_mutex);
 	BLI_condition_init(&pool->num_cond);
@@ -379,7 +373,7 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, c
 
 /**
  * Create a normal task pool.
- * This means that in mono-threaded context, it will not be executed at all until you call
+ * This means that in single-threaded context, it will not be executed at all until you call
  * \a BLI_task_pool_work_and_wait() on it.
  */
 TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
@@ -389,9 +383,13 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
 
 /**
  * Create a background task pool.
- * In multi-threaded context, there is no differences with \a BLI_task_pool_create(), but in mono-threaded case
+ * In multi-threaded context, there is no differences with \a BLI_task_pool_create(), but in single-threaded case
  * it is assured to have at least one worker thread to run on (i.e. you do not have to call
  * \a BLI_task_pool_work_and_wait() on it to be sure it will be processed).
+ *
+ * \note Background pools are non-recursive (that is, you should not create other background pools in tasks assigned
+ *       to a brackground pool, they could end never being executed, since the 'fallback' background thread is already
+ *       busy with parent task in single-threaded context).
  */
 TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, void *userdata)
 {




More information about the Bf-blender-cvs mailing list