123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- /*!
- * \file lib/gis/worker.c
- *
- * \brief GIS Library - Worker functions.
- *
- * (C) 2008-2014 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- *
- * \author Glynn Clements
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #ifdef HAVE_PTHREAD_H
- /****************************************************************************/
- #include <pthread.h>
- #define DEFAULT_WORKERS 0
- struct worker {
- void (*func)(void *);
- void *closure;
- void **ref;
- pthread_t thread;
- pthread_cond_t cond;
- pthread_mutex_t mutex;
- int cancel;
- };
- static int num_workers;
- static struct worker *workers;
- static pthread_cond_t worker_cond;
- static pthread_mutex_t worker_mutex;
- /****************************************************************************/
- static void *worker(void *arg)
- {
- struct worker *w = arg;
- while (!w->cancel) {
- pthread_mutex_lock(&w->mutex);
- while (!w->func)
- pthread_cond_wait(&w->cond, &w->mutex);
- (*w->func)(w->closure);
- w->func = NULL;
- w->closure = NULL;
- *w->ref = NULL;
- pthread_mutex_unlock(&w->mutex);
- pthread_cond_signal(&w->cond);
- pthread_cond_signal(&worker_cond);
- }
- return NULL;
- }
- static struct worker *get_worker(void)
- {
- int i;
- for (i = 0; i < num_workers; i++) {
- struct worker *w = &workers[i];
- if (!w->func)
- return w;
- }
- return NULL;
- }
- void G_begin_execute(void (*func)(void *), void *closure, void **ref, int force)
- {
- struct worker *w;
-
- if (*ref)
- G_fatal_error(_("Task already has a worker"));
- pthread_mutex_lock(&worker_mutex);
- while (w = get_worker(), force && num_workers > 0 && !w)
- pthread_cond_wait(&worker_cond, &worker_mutex);
- *ref = w;
- if (!w) {
- pthread_mutex_unlock(&worker_mutex);
- (*func)(closure);
- return;
- }
- pthread_mutex_lock(&w->mutex);
- w->func = func;
- w->closure = closure;
- w->ref = ref;
- pthread_cond_signal(&w->cond);
- pthread_mutex_unlock(&w->mutex);
- pthread_mutex_unlock(&worker_mutex);
- }
- void G_end_execute(void **ref)
- {
- struct worker *w = *ref;
- if (!w)
- return;
- pthread_mutex_lock(&w->mutex);
- while (*ref)
- pthread_cond_wait(&w->cond, &w->mutex);
- pthread_mutex_unlock(&w->mutex);
- }
- void G_init_workers(void)
- {
- const char *p = getenv("WORKERS");
- int i;
- pthread_mutex_init(&worker_mutex, NULL);
- pthread_cond_init(&worker_cond, NULL);
- num_workers = p ? atoi(p) : DEFAULT_WORKERS;
- workers = G_calloc(num_workers, sizeof(struct worker));
- for (i = 0; i < num_workers; i++) {
- struct worker *w = &workers[i];
- pthread_mutex_init(&w->mutex, NULL);
- pthread_cond_init(&w->cond, NULL);
- pthread_create(&w->thread, NULL, worker, w);
- }
- }
- void G_finish_workers(void)
- {
- int i;
- for (i = 0; i < num_workers; i++) {
- struct worker *w = &workers[i];
- w->cancel = 1;
- pthread_cancel(w->thread);
- }
- for (i = 0; i < num_workers; i++) {
- struct worker *w = &workers[i];
- pthread_join(w->thread, NULL);
- pthread_mutex_destroy(&w->mutex);
- pthread_cond_destroy(&w->cond);
- }
- pthread_mutex_destroy(&worker_mutex);
- pthread_cond_destroy(&worker_cond);
- }
- /****************************************************************************/
- #else
- /****************************************************************************/
- void G_begin_execute(void (*func)(void *), void *closure, void **ref, int force)
- {
- (*func)(closure);
- }
- void G_end_execute(void **ref)
- {
- }
- void G_init_workers(void)
- {
- }
- void G_finish_workers(void)
- {
- }
- /****************************************************************************/
- #endif
|