comparison mupdf-source/source/helpers/mu-threads/mu-threads.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2021 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/helpers/mu-threads.h"
24
25 #ifdef DISABLE_MUTHREADS
26
27 #include <stdlib.h>
28
29 /* Null implementation. Just error out. */
30
31 int mu_create_semaphore(mu_semaphore *sem)
32 {
33 return 1; /* Just Error */
34 }
35
36 void mu_destroy_semaphore(mu_semaphore *sem)
37 {
38 }
39
40 int mu_trigger_semaphore(mu_semaphore *sem)
41 {
42 abort();
43 return 1;
44 }
45
46 int mu_wait_semaphore(mu_semaphore *sem)
47 {
48 abort();
49 return 1;
50 }
51
52 int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
53 {
54 return 1;
55 }
56
57 void mu_destroy_thread(mu_thread *th)
58 {
59 }
60
61 int mu_create_mutex(mu_mutex *mutex)
62 {
63 return 1;
64 }
65
66 void mu_destroy_mutex(mu_mutex *mutex)
67 {
68 }
69
70 void mu_lock_mutex(mu_mutex *mutex)
71 {
72 abort();
73 }
74
75 void mu_unlock_mutex(mu_mutex *mutex)
76 {
77 abort();
78 }
79
80 #elif MU_THREAD_IMPL_TYPE == 1
81
82 /* Windows threads */
83 int mu_create_semaphore(mu_semaphore *sem)
84 {
85 sem->handle = CreateSemaphore(NULL, 0, 1, NULL);
86 return (sem->handle == NULL);
87 }
88
89 void mu_destroy_semaphore(mu_semaphore *sem)
90 {
91 if (sem->handle == NULL)
92 return;
93 /* We can't sensibly handle this failing */
94 (void)CloseHandle(sem->handle);
95 }
96
97 int mu_trigger_semaphore(mu_semaphore *sem)
98 {
99 if (sem->handle == NULL)
100 return 0;
101 /* We can't sensibly handle this failing */
102 return !ReleaseSemaphore(sem->handle, 1, NULL);
103 }
104
105 int mu_wait_semaphore(mu_semaphore *sem)
106 {
107 if (sem->handle == NULL)
108 return 0;
109 /* We can't sensibly handle this failing */
110 return !WaitForSingleObject(sem->handle, INFINITE);
111 }
112
113 static DWORD WINAPI thread_starter(LPVOID arg)
114 {
115 mu_thread *th = (mu_thread *)arg;
116
117 th->fn(th->arg);
118
119 return 0;
120 }
121
122 int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
123 {
124 th->fn = fn;
125 th->arg = arg;
126 th->handle = CreateThread(NULL, 0, thread_starter, th, 0, NULL);
127
128 return (th->handle == NULL);
129 }
130
131 void mu_destroy_thread(mu_thread *th)
132 {
133 if (th->handle == NULL)
134 return;
135 /* We can't sensibly handle this failing */
136 (void)WaitForSingleObject(th->handle, INFINITE);
137 (void)CloseHandle(th->handle);
138 th->handle = NULL;
139 }
140
141 int mu_create_mutex(mu_mutex *mutex)
142 {
143 InitializeCriticalSection(&mutex->mutex);
144 return 0; /* Magic function, never fails */
145 }
146
147 void mu_destroy_mutex(mu_mutex *mutex)
148 {
149 const static CRITICAL_SECTION empty = { 0 };
150 if (memcmp(&mutex->mutex, &empty, sizeof(empty)) == 0)
151 return;
152 DeleteCriticalSection(&mutex->mutex);
153 mutex->mutex = empty;
154 }
155
156 void mu_lock_mutex(mu_mutex *mutex)
157 {
158 EnterCriticalSection(&mutex->mutex);
159 }
160
161 void mu_unlock_mutex(mu_mutex *mutex)
162 {
163 LeaveCriticalSection(&mutex->mutex);
164 }
165
166 #elif MU_THREAD_IMPL_TYPE == 2
167
168 /*
169 PThreads - without working unnamed semaphores.
170
171 Neither ios nor OSX supports unnamed semaphores.
172 Named semaphores are a pain to use, so we implement
173 our own semaphores using condition variables and
174 mutexes.
175 */
176
177 #include <string.h>
178
179 int
180 mu_create_semaphore(mu_semaphore *sem)
181 {
182 int scode;
183
184 sem->count = 0;
185 scode = pthread_mutex_init(&sem->mutex, NULL);
186 if (scode == 0)
187 {
188 scode = pthread_cond_init(&sem->cond, NULL);
189 if (scode)
190 pthread_mutex_destroy(&sem->mutex);
191 }
192 if (scode)
193 memset(sem, 0, sizeof(*sem));
194 return scode;
195 }
196
197 void
198 mu_destroy_semaphore(mu_semaphore *sem)
199 {
200 const static mu_semaphore empty = { 0 };
201
202 if (memcmp(sem, &empty, sizeof(empty)) == 0)
203 return;
204 (void)pthread_cond_destroy(&sem->cond);
205 (void)pthread_mutex_destroy(&sem->mutex);
206 *sem = empty;
207 }
208
209 int
210 mu_wait_semaphore(mu_semaphore *sem)
211 {
212 int scode, scode2;
213
214 scode = pthread_mutex_lock(&sem->mutex);
215 if (scode)
216 return scode;
217 while (sem->count == 0) {
218 scode = pthread_cond_wait(&sem->cond, &sem->mutex);
219 if (scode)
220 break;
221 }
222 if (scode == 0)
223 --sem->count;
224 scode2 = pthread_mutex_unlock(&sem->mutex);
225 if (scode == 0)
226 scode = scode2;
227 return scode;
228 }
229
230 int
231 mu_trigger_semaphore(mu_semaphore * sem)
232 {
233 int scode, scode2;
234
235 scode = pthread_mutex_lock(&sem->mutex);
236 if (scode)
237 return scode;
238 if (sem->count++ == 0)
239 scode = pthread_cond_signal(&sem->cond);
240 scode2 = pthread_mutex_unlock(&sem->mutex);
241 if (scode == 0)
242 scode = scode2;
243 return scode;
244 }
245
246 static void *thread_starter(void *arg)
247 {
248 mu_thread *th = (mu_thread *)arg;
249
250 th->fn(th->arg);
251
252 return NULL;
253 }
254
255 int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
256 {
257 th->fn = fn;
258 th->arg = arg;
259 return pthread_create(&th->thread, NULL, thread_starter, th);
260 }
261
262 void mu_destroy_thread(mu_thread *th)
263 {
264 const static mu_thread empty; /* static objects are always initialized to zero */
265
266 if (memcmp(th, &empty, sizeof(empty)) == 0)
267 return;
268
269 (void)pthread_join(th->thread, NULL);
270 *th = empty;
271 }
272
273 int mu_create_mutex(mu_mutex *mutex)
274 {
275 return pthread_mutex_init(&mutex->mutex, NULL);
276 }
277
278 void mu_destroy_mutex(mu_mutex *mutex)
279 {
280 const static mu_mutex empty; /* static objects are always initialized to zero */
281
282 if (memcmp(mutex, &empty, sizeof(empty)) == 0)
283 return;
284
285 (void)pthread_mutex_destroy(&mutex->mutex);
286 *mutex = empty;
287 }
288
289 void mu_lock_mutex(mu_mutex *mutex)
290 {
291 (void)pthread_mutex_lock(&mutex->mutex);
292 }
293
294 void mu_unlock_mutex(mu_mutex *mutex)
295 {
296 (void)pthread_mutex_unlock(&mutex->mutex);
297 }
298
299 #else
300 #error Unknown MU_THREAD_IMPL_TYPE setting
301 #endif