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:
authorSergey Sharybin <sergey.vfx@gmail.com>2013-10-12 18:08:59 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2013-10-12 18:08:59 +0400
commitf0dcff9aa982d32bcb91e594df49a780ac376b5b (patch)
tree707bcc05ed6a1c6e5494d7d48ae8a07d5482c1ef /source/blender/blenlib/intern/threads.c
parent9d7567d6ac9b91d9754bb112fa388c83002a7fdc (diff)
Task scheduler ported form CYcles to C
Replaces ThreadedWorker and is gonna to be used for threaded object update in the future and some more upcoming changes. But in general, it's to be used for any task based subsystem in Blender. Originally written by Brecht, with some fixes and tweaks by self.
Diffstat (limited to 'source/blender/blenlib/intern/threads.c')
-rw-r--r--source/blender/blenlib/intern/threads.c114
1 files changed, 37 insertions, 77 deletions
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index c8b84d9310a..64682965649 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -37,6 +37,7 @@
#include "BLI_listbase.h"
#include "BLI_gsqueue.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "PIL_time.h"
@@ -63,6 +64,9 @@ extern pthread_key_t gomp_tls_key;
static void *thread_tls_data;
#endif
+/* We're using one global task scheduler for all kind of tasks. */
+static TaskScheduler *task_scheduler = NULL;
+
/* ********** basic thread control API ************
*
* Many thread cases have an X amount of jobs, and only an Y amount of
@@ -151,9 +155,26 @@ void BLI_threadapi_init(void)
void BLI_threadapi_exit(void)
{
+ if (task_scheduler) {
+ BLI_task_scheduler_free(task_scheduler);
+ }
BLI_spin_end(&_malloc_lock);
}
+TaskScheduler *BLI_task_scheduler_get(void)
+{
+ if (task_scheduler == NULL) {
+ int tot_thread = BLI_system_thread_count();
+
+ /* Do a lazy initialization, so it happes after
+ * command line arguments parsing
+ */
+ task_scheduler = BLI_task_scheduler_create(tot_thread);
+ }
+
+ return task_scheduler;
+}
+
/* tot = 0 only initializes malloc mutex in a safe way (see sequence.c)
* problem otherwise: scene render will kill of the mutex!
*/
@@ -419,6 +440,11 @@ void BLI_mutex_unlock(ThreadMutex *mutex)
pthread_mutex_unlock(mutex);
}
+bool BLI_mutex_trylock(ThreadMutex *mutex)
+{
+ return (pthread_mutex_trylock(mutex) == 0);
+}
+
void BLI_mutex_end(ThreadMutex *mutex)
{
pthread_mutex_destroy(mutex);
@@ -563,97 +589,31 @@ void BLI_ticket_mutex_unlock(TicketMutex *ticket)
/* ************************************************ */
-typedef struct ThreadedWorker {
- ListBase threadbase;
- void *(*work_fnct)(void *);
- char busy[RE_MAX_THREAD];
- int total;
- int sleep_time;
-} ThreadedWorker;
-
-typedef struct WorkParam {
- ThreadedWorker *worker;
- void *param;
- int index;
-} WorkParam;
+/* Condition */
-static void *exec_work_fnct(void *v_param)
+void BLI_condition_init(ThreadCondition *cond)
{
- WorkParam *p = (WorkParam *)v_param;
- void *value;
-
- value = p->worker->work_fnct(p->param);
-
- p->worker->busy[p->index] = 0;
- MEM_freeN(p);
-
- return value;
+ pthread_cond_init(cond, NULL);
}
-ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time)
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
{
- ThreadedWorker *worker;
-
- (void)sleep_time; /* unused */
-
- worker = MEM_callocN(sizeof(ThreadedWorker), "threadedworker");
-
- if (tot > RE_MAX_THREAD) {
- tot = RE_MAX_THREAD;
- }
- else if (tot < 1) {
- tot = 1;
- }
-
- worker->total = tot;
- worker->work_fnct = do_thread;
-
- BLI_init_threads(&worker->threadbase, exec_work_fnct, tot);
-
- return worker;
+ pthread_cond_wait(cond, mutex);
}
-void BLI_end_worker(ThreadedWorker *worker)
+void BLI_condition_notify_one(ThreadCondition *cond)
{
- BLI_remove_threads(&worker->threadbase);
+ pthread_cond_signal(cond);
}
-void BLI_destroy_worker(ThreadedWorker *worker)
+void BLI_condition_notify_all(ThreadCondition *cond)
{
- BLI_end_worker(worker);
- BLI_freelistN(&worker->threadbase);
- MEM_freeN(worker);
+ pthread_cond_broadcast(cond);
}
-void BLI_insert_work(ThreadedWorker *worker, void *param)
+void BLI_condition_end(ThreadCondition *cond)
{
- WorkParam *p = MEM_callocN(sizeof(WorkParam), "workparam");
- int index;
-
- if (BLI_available_threads(&worker->threadbase) == 0) {
- index = worker->total;
- while (index == worker->total) {
- PIL_sleep_ms(worker->sleep_time);
-
- for (index = 0; index < worker->total; index++) {
- if (worker->busy[index] == 0) {
- BLI_remove_thread_index(&worker->threadbase, index);
- break;
- }
- }
- }
- }
- else {
- index = BLI_available_thread_index(&worker->threadbase);
- }
-
- worker->busy[index] = 1;
-
- p->param = param;
- p->index = index;
- p->worker = worker;
-
- BLI_insert_thread(&worker->threadbase, p);
+ pthread_cond_destroy(cond);
}
/* ************************************************ */