diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/source/helpers/mu-threads/mu-threads.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,301 @@
+// Copyright (C) 2004-2021 Artifex Software, Inc.
+//
+// This file is part of MuPDF.
+//
+// MuPDF is free software: you can redistribute it and/or modify it under the
+// terms of the GNU Affero General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option)
+// any later version.
+//
+// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
+//
+// Alternative licensing terms are available from the licensor.
+// For commercial licensing, see <https://www.artifex.com/> or contact
+// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
+// CA 94129, USA, for further information.
+
+#include "mupdf/helpers/mu-threads.h"
+
+#ifdef DISABLE_MUTHREADS
+
+#include <stdlib.h>
+
+/* Null implementation. Just error out. */
+
+int mu_create_semaphore(mu_semaphore *sem)
+{
+	return 1; /* Just Error */
+}
+
+void mu_destroy_semaphore(mu_semaphore *sem)
+{
+}
+
+int mu_trigger_semaphore(mu_semaphore *sem)
+{
+	abort();
+	return 1;
+}
+
+int mu_wait_semaphore(mu_semaphore *sem)
+{
+	abort();
+	return 1;
+}
+
+int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
+{
+	return 1;
+}
+
+void mu_destroy_thread(mu_thread *th)
+{
+}
+
+int mu_create_mutex(mu_mutex *mutex)
+{
+	return 1;
+}
+
+void mu_destroy_mutex(mu_mutex *mutex)
+{
+}
+
+void mu_lock_mutex(mu_mutex *mutex)
+{
+	abort();
+}
+
+void mu_unlock_mutex(mu_mutex *mutex)
+{
+	abort();
+}
+
+#elif MU_THREAD_IMPL_TYPE == 1
+
+/* Windows threads */
+int mu_create_semaphore(mu_semaphore *sem)
+{
+	sem->handle = CreateSemaphore(NULL, 0, 1, NULL);
+	return (sem->handle == NULL);
+}
+
+void mu_destroy_semaphore(mu_semaphore *sem)
+{
+	if (sem->handle == NULL)
+		return;
+	/* We can't sensibly handle this failing */
+	(void)CloseHandle(sem->handle);
+}
+
+int mu_trigger_semaphore(mu_semaphore *sem)
+{
+	if (sem->handle == NULL)
+		return 0;
+	/* We can't sensibly handle this failing */
+	return !ReleaseSemaphore(sem->handle, 1, NULL);
+}
+
+int mu_wait_semaphore(mu_semaphore *sem)
+{
+	if (sem->handle == NULL)
+		return 0;
+	/* We can't sensibly handle this failing */
+	return !WaitForSingleObject(sem->handle, INFINITE);
+}
+
+static DWORD WINAPI thread_starter(LPVOID arg)
+{
+	mu_thread *th = (mu_thread *)arg;
+
+	th->fn(th->arg);
+
+	return 0;
+}
+
+int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
+{
+	th->fn = fn;
+	th->arg = arg;
+	th->handle = CreateThread(NULL, 0, thread_starter, th, 0, NULL);
+
+	return (th->handle == NULL);
+}
+
+void mu_destroy_thread(mu_thread *th)
+{
+	if (th->handle == NULL)
+		return;
+	/* We can't sensibly handle this failing */
+	(void)WaitForSingleObject(th->handle, INFINITE);
+	(void)CloseHandle(th->handle);
+	th->handle = NULL;
+}
+
+int mu_create_mutex(mu_mutex *mutex)
+{
+	InitializeCriticalSection(&mutex->mutex);
+	return 0; /* Magic function, never fails */
+}
+
+void mu_destroy_mutex(mu_mutex *mutex)
+{
+	const static CRITICAL_SECTION empty = { 0 };
+	if (memcmp(&mutex->mutex, &empty, sizeof(empty)) == 0)
+		return;
+	DeleteCriticalSection(&mutex->mutex);
+	mutex->mutex = empty;
+}
+
+void mu_lock_mutex(mu_mutex *mutex)
+{
+	EnterCriticalSection(&mutex->mutex);
+}
+
+void mu_unlock_mutex(mu_mutex *mutex)
+{
+	LeaveCriticalSection(&mutex->mutex);
+}
+
+#elif MU_THREAD_IMPL_TYPE == 2
+
+/*
+	PThreads - without working unnamed semaphores.
+
+	Neither ios nor OSX supports unnamed semaphores.
+	Named semaphores are a pain to use, so we implement
+	our own semaphores using condition variables and
+	mutexes.
+*/
+
+#include <string.h>
+
+int
+mu_create_semaphore(mu_semaphore *sem)
+{
+	int scode;
+
+	sem->count = 0;
+	scode = pthread_mutex_init(&sem->mutex, NULL);
+	if (scode == 0)
+	{
+		scode = pthread_cond_init(&sem->cond, NULL);
+		if (scode)
+			pthread_mutex_destroy(&sem->mutex);
+	}
+	if (scode)
+		memset(sem, 0, sizeof(*sem));
+	return scode;
+}
+
+void
+mu_destroy_semaphore(mu_semaphore *sem)
+{
+	const static mu_semaphore empty = { 0 };
+
+	if (memcmp(sem, &empty, sizeof(empty)) == 0)
+		return;
+	(void)pthread_cond_destroy(&sem->cond);
+	(void)pthread_mutex_destroy(&sem->mutex);
+	*sem = empty;
+}
+
+int
+mu_wait_semaphore(mu_semaphore *sem)
+{
+	int scode, scode2;
+
+	scode = pthread_mutex_lock(&sem->mutex);
+	if (scode)
+		return scode;
+	while (sem->count == 0) {
+		scode = pthread_cond_wait(&sem->cond, &sem->mutex);
+		if (scode)
+			break;
+	}
+	if (scode == 0)
+		--sem->count;
+	scode2 = pthread_mutex_unlock(&sem->mutex);
+	if (scode == 0)
+		scode = scode2;
+	return scode;
+}
+
+int
+mu_trigger_semaphore(mu_semaphore * sem)
+{
+	int scode, scode2;
+
+	scode = pthread_mutex_lock(&sem->mutex);
+	if (scode)
+		return scode;
+	if (sem->count++ == 0)
+		scode = pthread_cond_signal(&sem->cond);
+	scode2 = pthread_mutex_unlock(&sem->mutex);
+	if (scode == 0)
+		scode = scode2;
+	return scode;
+}
+
+static void *thread_starter(void *arg)
+{
+	mu_thread *th = (mu_thread *)arg;
+
+	th->fn(th->arg);
+
+	return NULL;
+}
+
+int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg)
+{
+	th->fn = fn;
+	th->arg = arg;
+	return pthread_create(&th->thread, NULL, thread_starter, th);
+}
+
+void mu_destroy_thread(mu_thread *th)
+{
+	const static mu_thread empty; /* static objects are always initialized to zero */
+
+	if (memcmp(th, &empty, sizeof(empty)) == 0)
+		return;
+
+	(void)pthread_join(th->thread, NULL);
+	*th = empty;
+}
+
+int mu_create_mutex(mu_mutex *mutex)
+{
+	return pthread_mutex_init(&mutex->mutex, NULL);
+}
+
+void mu_destroy_mutex(mu_mutex *mutex)
+{
+	const static mu_mutex empty; /* static objects are always initialized to zero */
+
+	if (memcmp(mutex, &empty, sizeof(empty)) == 0)
+		return;
+
+	(void)pthread_mutex_destroy(&mutex->mutex);
+	*mutex = empty;
+}
+
+void mu_lock_mutex(mu_mutex *mutex)
+{
+	(void)pthread_mutex_lock(&mutex->mutex);
+}
+
+void mu_unlock_mutex(mu_mutex *mutex)
+{
+	(void)pthread_mutex_unlock(&mutex->mutex);
+}
+
+#else
+#error Unknown MU_THREAD_IMPL_TYPE setting
+#endif