GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
worker.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/worker.c
3 *
4 * \brief GIS Library - Worker functions.
5 *
6 * (C) 2008-2014 by the GRASS Development Team
7 *
8 * This program is free software under the GNU General Public License
9 * (>=v2). Read the file COPYING that comes with GRASS for details.
10 *
11 * \author Glynn Clements
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <grass/gis.h>
17#include <grass/glocale.h>
18
19#ifdef HAVE_PTHREAD_H
20
21/****************************************************************************/
22
23#include <pthread.h>
24
25#define DEFAULT_WORKERS 0
26
27struct worker {
28 void (*func)(void *);
29 void *closure;
30 void **ref;
31 pthread_t thread;
32 pthread_cond_t cond;
33 pthread_mutex_t mutex;
34 int cancel;
35};
36
37static int num_workers;
38static struct worker *workers;
39static pthread_cond_t worker_cond;
40static pthread_mutex_t worker_mutex;
41
42/****************************************************************************/
43
44static void *worker(void *arg)
45{
46 struct worker *w = arg;
47
48 while (!w->cancel) {
49 pthread_mutex_lock(&w->mutex);
50 while (!w->func)
51 pthread_cond_wait(&w->cond, &w->mutex);
52
53 (*w->func)(w->closure);
54
55 w->func = NULL;
56 w->closure = NULL;
57 *w->ref = NULL;
58 pthread_mutex_unlock(&w->mutex);
59 pthread_cond_signal(&w->cond);
60 pthread_cond_signal(&worker_cond);
61 }
62
63 return NULL;
64}
65
66static struct worker *get_worker(void)
67{
68 int i;
69
70 for (i = 0; i < num_workers; i++) {
71 struct worker *w = &workers[i];
72
73 if (!w->func)
74 return w;
75 }
76
77 return NULL;
78}
79
80void G_begin_execute(void (*func)(void *), void *closure, void **ref, int force)
81{
82 struct worker *w;
83
84 if (*ref)
85 G_fatal_error(_("Task already has a worker"));
86
87 pthread_mutex_lock(&worker_mutex);
88
89 while (w = get_worker(), force && num_workers > 0 && !w)
90 pthread_cond_wait(&worker_cond, &worker_mutex);
91 *ref = w;
92
93 if (!w) {
94 pthread_mutex_unlock(&worker_mutex);
95 (*func)(closure);
96 return;
97 }
98
99 pthread_mutex_lock(&w->mutex);
100 w->func = func;
101 w->closure = closure;
102 w->ref = ref;
103 pthread_cond_signal(&w->cond);
104 pthread_mutex_unlock(&w->mutex);
105
106 pthread_mutex_unlock(&worker_mutex);
107}
108
109void G_end_execute(void **ref)
110{
111 struct worker *w = *ref;
112
113 if (!w)
114 return;
115
116 pthread_mutex_lock(&w->mutex);
117 while (*ref)
118 pthread_cond_wait(&w->cond, &w->mutex);
119 pthread_mutex_unlock(&w->mutex);
120}
121
122void G_init_workers(void)
123{
124 const char *p = getenv("WORKERS");
125 int i;
126
127 pthread_mutex_init(&worker_mutex, NULL);
128 pthread_cond_init(&worker_cond, NULL);
129
130 num_workers = p ? atoi(p) : DEFAULT_WORKERS;
131 workers = G_calloc(num_workers, sizeof(struct worker));
132
133 for (i = 0; i < num_workers; i++) {
134 struct worker *w = &workers[i];
135
136 pthread_mutex_init(&w->mutex, NULL);
137 pthread_cond_init(&w->cond, NULL);
138 pthread_create(&w->thread, NULL, worker, w);
139 }
140}
141
142void G_finish_workers(void)
143{
144 int i;
145
146 for (i = 0; i < num_workers; i++) {
147 struct worker *w = &workers[i];
148
149 w->cancel = 1;
150 pthread_cancel(w->thread);
151 }
152
153 for (i = 0; i < num_workers; i++) {
154 struct worker *w = &workers[i];
155
156 pthread_join(w->thread, NULL);
157 pthread_mutex_destroy(&w->mutex);
158 pthread_cond_destroy(&w->cond);
159 }
160
161 pthread_mutex_destroy(&worker_mutex);
162 pthread_cond_destroy(&worker_cond);
163}
164
165/****************************************************************************/
166
167#else
168
169/****************************************************************************/
170
171void G_begin_execute(void (*func)(void *), void *closure, void **ref UNUSED,
172 int force UNUSED)
173{
174 (*func)(closure);
175}
176
177void G_end_execute(void **ref UNUSED)
178{
179}
180
182{
183}
184
186{
187}
188
189/****************************************************************************/
190
191#endif
#define NULL
Definition ccmath.h:32
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
void G_end_execute(void **ref UNUSED)
Definition worker.c:177
void G_init_workers(void)
Definition worker.c:181
void G_finish_workers(void)
Definition worker.c:185
void G_begin_execute(void(*func)(void *), void *closure, void **ref UNUSED, int force UNUSED)
Definition worker.c:171