| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // 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
|