GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
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 * SPDX-FileCopyrightText: 2008-2014 GRASS Development Team
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 *
9 * \author Glynn Clements
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <grass/gis.h>
15#include <grass/glocale.h>
16
17#ifdef HAVE_PTHREAD_H
18
19/****************************************************************************/
20
21#include <pthread.h>
22
23#define DEFAULT_WORKERS 0
24
25struct worker {
26 void (*func)(void *);
27 void *closure;
28 void **ref;
32 int cancel;
33};
34
35static int num_workers;
36static struct worker *workers;
39
40/****************************************************************************/
41
42static void *worker(void *arg)
43{
44 struct worker *w = arg;
45
46 while (!w->cancel) {
47 pthread_mutex_lock(&w->mutex);
48 while (!w->func)
49 pthread_cond_wait(&w->cond, &w->mutex);
50
51 (*w->func)(w->closure);
52
53 w->func = NULL;
54 w->closure = NULL;
55 *w->ref = NULL;
56 pthread_mutex_unlock(&w->mutex);
57 pthread_cond_signal(&w->cond);
59 }
60
61 return NULL;
62}
63
64static struct worker *get_worker(void)
65{
66 int i;
67
68 for (i = 0; i < num_workers; i++) {
69 struct worker *w = &workers[i];
70
71 if (!w->func)
72 return w;
73 }
74
75 return NULL;
76}
77
78void G_begin_execute(void (*func)(void *), void *closure, void **ref, int force)
79{
80 struct worker *w;
81
82 if (*ref)
83 G_fatal_error(_("Task already has a worker"));
84
86
87 while (w = get_worker(), force && num_workers > 0 && !w)
89 *ref = w;
90
91 if (!w) {
93 (*func)(closure);
94 return;
95 }
96
97 pthread_mutex_lock(&w->mutex);
98 w->func = func;
99 w->closure = closure;
100 w->ref = ref;
101 pthread_cond_signal(&w->cond);
102 pthread_mutex_unlock(&w->mutex);
103
105}
106
107void G_end_execute(void **ref)
108{
109 struct worker *w = *ref;
110
111 if (!w)
112 return;
113
114 pthread_mutex_lock(&w->mutex);
115 while (*ref)
116 pthread_cond_wait(&w->cond, &w->mutex);
117 pthread_mutex_unlock(&w->mutex);
118}
119
120void G_init_workers(void)
121{
122 const char *p = getenv("WORKERS");
123 int i;
124
127
129 workers = G_calloc(num_workers, sizeof(struct worker));
130
131 for (i = 0; i < num_workers; i++) {
132 struct worker *w = &workers[i];
133
134 pthread_mutex_init(&w->mutex, NULL);
135 pthread_cond_init(&w->cond, NULL);
136 pthread_create(&w->thread, NULL, worker, w);
137 }
138}
139
140void G_finish_workers(void)
141{
142 int i;
143
144 for (i = 0; i < num_workers; i++) {
145 struct worker *w = &workers[i];
146
147 w->cancel = 1;
148 pthread_cancel(w->thread);
149 }
150
151 for (i = 0; i < num_workers; i++) {
152 struct worker *w = &workers[i];
153
154 pthread_join(w->thread, NULL);
155 pthread_mutex_destroy(&w->mutex);
156 pthread_cond_destroy(&w->cond);
157 }
158
161}
162
163/****************************************************************************/
164
165#else
166
167/****************************************************************************/
168
169void G_begin_execute(void (*func)(void *), void *closure, void **ref G_UNUSED,
170 int force G_UNUSED)
171{
172 (*func)(closure);
173}
174
176{
177}
178
180{
181}
182
184{
185}
186
187/****************************************************************************/
188
189#endif
#define NULL
Definition ccmath.h:32
#define G_calloc(m, n)
Definition defs/gis.h:137
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define G_UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition gis.h:43
#define _(str)
Definition glocale.h:10
void G_init_workers(void)
Definition worker.c:179
void G_finish_workers(void)
Definition worker.c:183
void G_begin_execute(void(*func)(void *), void *closure, void **ref, int force)
Definition worker.c:169
void G_end_execute(void **ref)
Definition worker.c:175