diff options
Diffstat (limited to 'source/blender/blenlib/intern/threads.c')
-rw-r--r-- | source/blender/blenlib/intern/threads.c | 173 |
1 files changed, 172 insertions, 1 deletions
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 1f05070b034..9df8bbc81e3 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -1,6 +1,6 @@ /** * - * $Id: + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -38,6 +38,17 @@ #include "BLI_blenlib.h" #include "BLI_threads.h" +#include "PIL_time.h" + +/* for checking system threads - BLI_system_thread_count */ +#ifdef WIN32 +#include "Windows.h" +#elif defined(__APPLE__) +#include <sys/types.h> +#include <sys/sysctl.h> +#else +#include <unistd.h> +#endif /* ********** basic thread control API ************ @@ -190,6 +201,34 @@ void BLI_remove_thread(ListBase *threadbase, void *callerdata) } } +void BLI_remove_thread_index(ListBase *threadbase, int index) +{ + ThreadSlot *tslot; + int counter=0; + + for(tslot = threadbase->first; tslot; tslot = tslot->next, counter++) { + if (counter == index && tslot->avail == 0) { + tslot->callerdata = NULL; + pthread_join(tslot->pthread, NULL); + tslot->avail = 1; + break; + } + } +} + +void BLI_remove_threads(ListBase *threadbase) +{ + ThreadSlot *tslot; + + for(tslot = threadbase->first; tslot; tslot = tslot->next) { + if (tslot->avail == 0) { + tslot->callerdata = NULL; + pthread_join(tslot->pthread, NULL); + tslot->avail = 1; + } + } +} + void BLI_end_threads(ListBase *threadbase) { ThreadSlot *tslot; @@ -224,4 +263,136 @@ void BLI_unlock_thread(int type) pthread_mutex_unlock(&_custom1_lock); } +/* how many threads are native on this system? */ +int BLI_system_thread_count( void ) +{ + int t; +#ifdef WIN32 + SYSTEM_INFO info; + GetSystemInfo(&info); + t = (int) info.dwNumberOfProcessors; +#else +# ifdef __APPLE__ + int mib[2]; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(t); + sysctl(mib, 2, &t, &len, NULL, 0); +# elif defined(__sgi) + t = sysconf(_SC_NPROC_ONLN); +# else + t = (int)sysconf(_SC_NPROCESSORS_ONLN); +# endif +#endif + + if (t>RE_MAX_THREAD) + return RE_MAX_THREAD; + if (t<1) + return 1; + + return t; +} + +/* ************************************************ */ + +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; + +void *exec_work_fnct(void *v_param) +{ + 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; +} + +ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time) +{ + ThreadedWorker *worker; + + 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; +} + +void BLI_end_worker(ThreadedWorker *worker) +{ + BLI_remove_threads(&worker->threadbase); +} + +void BLI_destroy_worker(ThreadedWorker *worker) +{ + BLI_end_worker(worker); + BLI_freelistN(&worker->threadbase); + MEM_freeN(worker); +} + +void BLI_insert_work(ThreadedWorker *worker, void *param) +{ + 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); +} + /* eof */ |