diff --git a/src/Makefile.am b/src/Makefile.am index c52a7a095..de080e760 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,6 +36,7 @@ cairo_base_sources = \ cairo-matrix.c \ cairo-mutex.c \ cairo-mutex-private.h \ + cairo-mutex-impl-private.h \ cairo-mutex-type-private.h \ cairo-path.c \ cairo-path-private.h \ diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h new file mode 100644 index 000000000..6905566fc --- /dev/null +++ b/src/cairo-mutex-impl-private.h @@ -0,0 +1,226 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2002 University of Southern California + * Copyright © 2005,2007 Red Hat, Inc. + * Copyright © 2007 Mathias Hasselmann + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Carl D. Worth + * Mathias Hasselmann + * Behdad Esfahbod + */ + +#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H +#define CAIRO_MUTEX_IMPL_PRIVATE_H + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +CAIRO_BEGIN_DECLS + + +/* A fully qualified no-operation statement */ +#define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0) +/* And one that evaluates it's argument once */ +#define CAIRO_MUTEX_IMPL_NOOP1(expr) do { if (expr) ; } while (0) + + +/* Cairo mutex implementation: + * + * Any new mutex implementation needs to do the following: + * + * - Condition on the right header or feature. Headers are + * preferred as eg. you still can use win32 mutex implementation + * on a win32 system even if you do not compile the win32 + * surface/backend. + * + * - typedef #cairo_mutex_impl_t to the proper mutex type on your target + * system. Note that you may or may not need to use a pointer, + * depending on what kinds of initialization your mutex + * implementation supports. No trailing semicolon needed. + * You should be able to compile the following snippet (don't try + * running it): + * + * + * cairo_mutex_impl_t _cairo_some_mutex; + * + * + * - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to + * proper statement to lock/unlock the mutex object passed in. + * You can (and should) assume that the mutex is already + * initialized, and is-not-already-locked/is-locked, + * respectively. Use the "do { ... } while (0)" idiom if necessary. + * No trailing semicolons are needed (in any macro you define here). + * You should be able to compile the following snippet: + * + * + * cairo_mutex_impl_t _cairo_some_mutex; + * + * if (1) + * CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex); + * else + * CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex); + * + * + * - #define %CAIRO_MUTEX_IMPL_NIL_INITIALIZER to something that can + * initialize the #cairo_mutex_impl_t type you defined. Most of the + * time one of 0, %NULL, or {} works. At this point + * you should be able to compile the following snippet: + * + * + * cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; + * + * if (1) + * CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex); + * else + * CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex); + * + * + * - If the above code is not enough to initialize a mutex on + * your platform, #define CAIRO_MUTEX_IMPL_INIT(mutex) to statement + * to initialize the mutex (allocate resources, etc). Such that + * you should be able to compile AND RUN the following snippet: + * + * + * cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; + * + * CAIRO_MUTEX_IMPL_INIT (_cairo_some_mutex); + * + * if (1) + * CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex); + * else + * CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex); + * + * + * - If you define CAIRO_MUTEX_IMPL_INIT(mutex), cairo will use it to + * initialize all static mutex'es. If for any reason that should + * not happen (eg. %CAIRO_MUTEX_IMPL_INIT is just a faster way than + * what cairo does using %CAIRO_MUTEX_IMPL_NIL_INITIALIZER), then + * + * #define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP + * + * + * - If your system supports freeing a mutex object (deallocating + * resources, etc), then #define CAIRO_MUTEX_IMPL_FINI(mutex) to do + * that. + * + * - If you define CAIRO_MUTEX_IMPL_FINI(mutex), cairo will use it to + * define a finalizer function to finalize all static mutex'es. + * However, it's up to you to call CAIRO_MUTEX_IMPL_FINALIZE() at + * proper places, eg. when the system is unloading the cairo library. + * So, if for any reason finalizing static mutex'es is not needed + * (eg. you never call CAIRO_MUTEX_IMPL_FINALIZE()), then + * + * #define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP + * + * + * - That is all. If for any reason you think the above API is + * not enough to implement #cairo_mutex_impl_t on your system, please + * stop and write to the cairo mailing list about it. DO NOT + * poke around cairo-mutex-private.h for possible solutions. + */ + +#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H +#error "Do not include cairo-mutex-impl-private.h directly. Include cairo-mutex-type-private.h instead." +#endif + +#if CAIRO_NO_MUTEX + +/* No mutexes */ + + typedef int cairo_mutex_impl_t; + +# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP +# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) +# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) +# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 + +#elif HAVE_PTHREAD_H /*******************************************************/ + +# include + + typedef pthread_mutex_t cairo_mutex_impl_t; + +# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex)) +# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) +# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex)) +# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP +# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER + +#elif HAVE_WINDOWS_H /*******************************************************/ + +# include + + typedef CRITICAL_SECTION cairo_mutex_impl_t; + +# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex)) +# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex)) +# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex)) +# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex)) +# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 } + +#elif defined __OS2__ /******************************************************/ + +# define INCL_BASE +# define INCL_PM +# include + + typedef HMTX cairo_mutex_impl_t; + +# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT) +# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex) +# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE) +# define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex) +# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 + +#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/ + + typedef BLocker* cairo_mutex_impl_t; + +# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock() +# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock() +# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker() +# define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex) +# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL + +#else /**********************************************************************/ + +# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support." + + +#endif + +CAIRO_END_DECLS + +#endif diff --git a/src/cairo-mutex-private.h b/src/cairo-mutex-private.h index 64afd6480..61b87d7ad 100644 --- a/src/cairo-mutex-private.h +++ b/src/cairo-mutex-private.h @@ -41,136 +41,27 @@ #ifndef CAIRO_MUTEX_PRIVATE_H #define CAIRO_MUTEX_PRIVATE_H -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "cairo-compiler-private.h" #include "cairo-mutex-type-private.h" -/* Only the following three are mandatory at this point */ -#ifndef CAIRO_MUTEX_LOCK -# error "CAIRO_MUTEX_LOCK not defined. Check cairo-mutex-type-private.h." -#endif -#ifndef CAIRO_MUTEX_UNLOCK -# error "CAIRO_MUTEX_UNLOCK not defined. Check cairo-mutex-type-private.h." -#endif -#ifndef CAIRO_MUTEX_NIL_INITIALIZER -# error "CAIRO_MUTEX_NIL_INITIALIZER not defined. Check cairo-mutex-type-private.h." -#endif - CAIRO_BEGIN_DECLS - -#define CAIRO_MUTEX_DECLARE(mutex) extern cairo_mutex_t mutex -#include "cairo-mutex-list-private.h" -#undef CAIRO_MUTEX_DECLARE - - -/* make sure implementations don't fool us: we decide these ourself */ -#undef _CAIRO_MUTEX_USE_STATIC_INITIALIZER -#undef _CAIRO_MUTEX_USE_STATIC_FINALIZER - - -#ifdef CAIRO_MUTEX_INIT - -/* If %CAIRO_MUTEX_INIT is defined, we may need to initialize all - * static mutex'es. */ -# ifndef CAIRO_MUTEX_INITIALIZE -# define CAIRO_MUTEX_INITIALIZE() do { \ - if (!_cairo_mutex_initialized) \ - _cairo_mutex_initialize (); \ - } while(0) - - cairo_private void _cairo_mutex_initialize (void); - - /* and make sure we implement the above */ -# define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 1 -# endif /* CAIRO_MUTEX_INITIALIZE */ - -#else /* no CAIRO_MUTEX_INIT */ - -/* Otherwise we probably don't need to initialize static mutex'es, */ -# ifndef CAIRO_MUTEX_INITIALIZE -# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP -# endif /* CAIRO_MUTEX_INITIALIZE */ - -/* and dynamic ones can be initialized using the static initializer. */ -# define CAIRO_MUTEX_INIT(mutex) do { \ - cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_NIL_INITIALIZER; \ - memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \ - } while (0) - -#endif /* CAIRO_MUTEX_INIT */ - - -#ifdef CAIRO_MUTEX_FINI - -/* If %CAIRO_MUTEX_FINI is defined, we may need to finalize all - * static mutex'es. */ -# ifndef CAIRO_MUTEX_FINALIZE -# define CAIRO_MUTEX_FINALIZE() do { \ - if (_cairo_mutex_initialized) \ - _cairo_mutex_finalize (); \ - } while(0) - - cairo_private void _cairo_mutex_finalize (void); - - /* and make sure we implement the above */ -# define _CAIRO_MUTEX_USE_STATIC_FINALIZER 1 -# endif /* CAIRO_MUTEX_FINALIZE */ - -#else /* no CAIRO_MUTEX_FINI */ - -/* Otherwise we probably don't need to finalize static mutex'es, */ -# ifndef CAIRO_MUTEX_FINALIZE -# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP -# endif /* CAIRO_MUTEX_FINALIZE */ - -/* neither do the dynamic ones. */ -# define CAIRO_MUTEX_FINI(mutex) CAIRO_MUTEX_NOOP1(mutex) - -#endif /* CAIRO_MUTEX_FINI */ - - -#ifndef _CAIRO_MUTEX_USE_STATIC_INITIALIZER -#define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 0 +#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER +cairo_private void _cairo_mutex_initialize (void); #endif -#ifndef _CAIRO_MUTEX_USE_STATIC_FINALIZER -#define _CAIRO_MUTEX_USE_STATIC_FINALIZER 0 +#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER +cairo_private void _cairo_mutex_finalize (void); #endif - /* only if using static initializer and/or finalizer define the boolean */ -#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER +#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER cairo_private extern cairo_bool_t _cairo_mutex_initialized; #endif +/* Finally, extern the static mutexes and undef */ + +#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex +#include "cairo-mutex-list-private.h" +#undef CAIRO_MUTEX_DECLARE CAIRO_END_DECLS -/* Make sure everything we want is defined */ -#ifndef CAIRO_MUTEX_INITIALIZE -# error "CAIRO_MUTEX_INITIALIZE not defined" -#endif -#ifndef CAIRO_MUTEX_FINALIZE -# error "CAIRO_MUTEX_FINALIZE not defined" -#endif -#ifndef CAIRO_MUTEX_LOCK -# error "CAIRO_MUTEX_LOCK not defined" -#endif -#ifndef CAIRO_MUTEX_UNLOCK -# error "CAIRO_MUTEX_UNLOCK not defined" -#endif -#ifndef CAIRO_MUTEX_INIT -# error "CAIRO_MUTEX_INIT not defined" -#endif -#ifndef CAIRO_MUTEX_FINI -# error "CAIRO_MUTEX_FINI not defined" -#endif -#ifndef CAIRO_MUTEX_NIL_INITIALIZER -# error "CAIRO_MUTEX_NIL_INITIALIZER not defined" -#endif - #endif diff --git a/src/cairo-mutex-type-private.h b/src/cairo-mutex-type-private.h index f68afb77f..3dc5f4981 100644 --- a/src/cairo-mutex-type-private.h +++ b/src/cairo-mutex-type-private.h @@ -47,176 +47,161 @@ #include -CAIRO_BEGIN_DECLS - - -/* A fully qualified no-operation statement */ -#define CAIRO_MUTEX_NOOP do {/*no-op*/} while (0) -/* And one that evaluates it's argument once */ -#define CAIRO_MUTEX_NOOP1(expr) do { if (expr) ; } while (0) - - -/* Cairo mutex implementation: - * - * Any new mutex implementation needs to do the following: - * - * - Condition on the right header or feature. Headers are - * preferred as eg. you still can use win32 mutex implementation - * on a win32 system even if you do not compile the win32 - * surface/backend. - * - * - typedef #cairo_mutex_t to the proper mutex type on your target - * system. Note that you may or may not need to use a pointer, - * depending on what kinds of initialization your mutex - * implementation supports. No trailing semicolon needed. - * You should be able to compile the following snippet (don't try - * running it): - * - * - * cairo_mutex_t _cairo_some_mutex; - * - * - * - #define CAIRO_MUTEX_LOCK(mutex) and CAIRO_MUTEX_UNLOCK(mutex) to - * proper statement to lock/unlock the mutex object passed in. - * You can (and should) assume that the mutex is already - * initialized, and is-not-already-locked/is-locked, - * respectively. Use the "do { ... } while (0)" idiom if necessary. - * No trailing semicolons are needed (in any macro you define here). - * You should be able to compile the following snippet: - * - * - * cairo_mutex_t _cairo_some_mutex; - * - * if (1) - * CAIRO_MUTEX_LOCK (_cairo_some_mutex); - * else - * CAIRO_MUTEX_UNLOCK (_cairo_some_mutex); - * - * - * - #define %CAIRO_MUTEX_NIL_INITIALIZER to something that can - * initialize the #cairo_mutex_t type you defined. Most of the - * time one of 0, %NULL, or {} works. At this point - * you should be able to compile the following snippet: - * - * - * cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER; - * - * if (1) - * CAIRO_MUTEX_LOCK (_cairo_some_mutex); - * else - * CAIRO_MUTEX_UNLOCK (_cairo_some_mutex); - * - * - * - If the above code is not enough to initialize a mutex on - * your platform, #define CAIRO_MUTEX_INIT(mutex) to statement - * to initialize the mutex (allocate resources, etc). Such that - * you should be able to compile AND RUN the following snippet: - * - * - * cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER; - * - * CAIRO_MUTEX_INIT (_cairo_some_mutex); - * - * if (1) - * CAIRO_MUTEX_LOCK (_cairo_some_mutex); - * else - * CAIRO_MUTEX_UNLOCK (_cairo_some_mutex); - * - * - * - If you define CAIRO_MUTEX_INIT(mutex), cairo will use it to - * initialize all static mutex'es. If for any reason that should - * not happen (eg. %CAIRO_MUTEX_INIT is just a faster way than - * what cairo does using %CAIRO_MUTEX_NIL_INITIALIZER), then - * - * #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP - * - * - * - If your system supports freeing a mutex object (deallocating - * resources, etc), then #define CAIRO_MUTEX_FINI(mutex) to do - * that. - * - * - If you define CAIRO_MUTEX_FINI(mutex), cairo will use it to - * define a finalizer function to finalize all static mutex'es. - * However, it's up to you to call CAIRO_MUTEX_FINALIZE() at - * proper places, eg. when the system is unloading the cairo library. - * So, if for any reason finalizing static mutex'es is not needed - * (eg. you never call CAIRO_MUTEX_FINALIZE()), then - * - * #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP - * - * - * - That is all. If for any reason you think the above API is - * not enough to implement #cairo_mutex_t on your system, please - * stop and write to the cairo mailing list about it. DO NOT - * poke around cairo-mutex-private.h for possible solutions. - */ - -#if CAIRO_NO_MUTEX - -/* No mutexes */ - - typedef int cairo_mutex_t; - -# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP -# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP1(mutex) -# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP1(mutex) -# define CAIRO_MUTEX_NIL_INITIALIZER 0 - -#elif HAVE_PTHREAD_H /*******************************************************/ - -# include - - typedef pthread_mutex_t cairo_mutex_t; - -# define CAIRO_MUTEX_LOCK(mutex) pthread_mutex_lock (&(mutex)) -# define CAIRO_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) -# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (&(mutex)) -# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP -# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER - -#elif HAVE_WINDOWS_H /*******************************************************/ - -# include - - typedef CRITICAL_SECTION cairo_mutex_t; - -# define CAIRO_MUTEX_LOCK(mutex) EnterCriticalSection (&(mutex)) -# define CAIRO_MUTEX_UNLOCK(mutex) LeaveCriticalSection (&(mutex)) -# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (&(mutex)) -# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (&(mutex)) -# define CAIRO_MUTEX_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 } - -#elif defined __OS2__ /******************************************************/ - -# define INCL_BASE -# define INCL_PM -# include - - typedef HMTX cairo_mutex_t; - -# define CAIRO_MUTEX_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT) -# define CAIRO_MUTEX_UNLOCK(mutex) DosReleaseMutexSem(mutex) -# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE) -# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (mutex) -# define CAIRO_MUTEX_NIL_INITIALIZER 0 - -#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/ - - typedef BLocker* cairo_mutex_t; - -# define CAIRO_MUTEX_LOCK(mutex) (mutex)->Lock() -# define CAIRO_MUTEX_UNLOCK(mutex) (mutex)->Unlock() -# define CAIRO_MUTEX_INIT(mutex) (mutex) = new BLocker() -# define CAIRO_MUTEX_FINI(mutex) delete (mutex) -# define CAIRO_MUTEX_NIL_INITIALIZER NULL - -#else /**********************************************************************/ - -# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support." - +#include "cairo-compiler-private.h" +#include "cairo-mutex-impl-private.h" +/* Only the following three are mandatory at this point */ +#ifndef CAIRO_MUTEX_IMPL_LOCK +# error "CAIRO_MUTEX_IMPL_LOCK not defined. Check cairo-mutex-impl-private.h." +#endif +#ifndef CAIRO_MUTEX_IMPL_UNLOCK +# error "CAIRO_MUTEX_IMPL_UNLOCK not defined. Check cairo-mutex-impl-private.h." +#endif +#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER +# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined. Check cairo-mutex-impl-private.h." #endif -CAIRO_END_DECLS + +/* make sure implementations don't fool us: we decide these ourself */ +#undef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER +#undef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER + + +#ifdef CAIRO_MUTEX_IMPL_INIT + +/* If %CAIRO_MUTEX_IMPL_INIT is defined, we may need to initialize all + * static mutex'es. */ +# ifndef CAIRO_MUTEX_IMPL_INITIALIZE +# define CAIRO_MUTEX_IMPL_INITIALIZE() do { \ + if (!_cairo_mutex_initialized) \ + _cairo_mutex_initialize (); \ + } while(0) + + /* and make sure we implement the above */ +# define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 1 +# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */ + +#else /* no CAIRO_MUTEX_IMPL_INIT */ + +/* Otherwise we probably don't need to initialize static mutex'es, */ +# ifndef CAIRO_MUTEX_IMPL_INITIALIZE +# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP +# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */ + +/* and dynamic ones can be initialized using the static initializer. */ +# define CAIRO_MUTEX_IMPL_INIT(mutex) do { \ + cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; \ + memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \ + } while (0) + +#endif /* CAIRO_MUTEX_IMPL_INIT */ + + +#ifdef CAIRO_MUTEX_IMPL_FINI + +/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all + * static mutex'es. */ +# ifndef CAIRO_MUTEX_IMPL_FINALIZE +# define CAIRO_MUTEX_IMPL_FINALIZE() do { \ + if (_cairo_mutex_initialized) \ + _cairo_mutex_finalize (); \ + } while(0) + + /* and make sure we implement the above */ +# define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 1 +# endif /* CAIRO_MUTEX_IMPL_FINALIZE */ + +#else /* no CAIRO_MUTEX_IMPL_FINI */ + +/* Otherwise we probably don't need to finalize static mutex'es, */ +# ifndef CAIRO_MUTEX_IMPL_FINALIZE +# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP +# endif /* CAIRO_MUTEX_IMPL_FINALIZE */ + +/* neither do the dynamic ones. */ +# define CAIRO_MUTEX_IMPL_FINI(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) + +#endif /* CAIRO_MUTEX_IMPL_FINI */ + + +#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER +#define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 0 +#endif +#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER +#define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 0 +#endif + + +/* Make sure everything we want is defined */ +#ifndef CAIRO_MUTEX_IMPL_INITIALIZE +# error "CAIRO_MUTEX_IMPL_INITIALIZE not defined" +#endif +#ifndef CAIRO_MUTEX_IMPL_FINALIZE +# error "CAIRO_MUTEX_IMPL_FINALIZE not defined" +#endif +#ifndef CAIRO_MUTEX_IMPL_LOCK +# error "CAIRO_MUTEX_IMPL_LOCK not defined" +#endif +#ifndef CAIRO_MUTEX_IMPL_UNLOCK +# error "CAIRO_MUTEX_IMPL_UNLOCK not defined" +#endif +#ifndef CAIRO_MUTEX_IMPL_INIT +# error "CAIRO_MUTEX_IMPL_INIT not defined" +#endif +#ifndef CAIRO_MUTEX_IMPL_FINI +# error "CAIRO_MUTEX_IMPL_FINI not defined" +#endif +#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER +# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined" +#endif + + +/* Public interface. */ + +/* By default it simply uses the implementation provided. + * But we can provide for debugging features by overriding them */ + +#ifndef CAIRO_MUTEX_DEBUG +typedef cairo_mutex_impl_t cairo_mutex_t; +#else +# define cairo_mutex_t cairo_mutex_impl_t +#endif + +#define CAIRO_MUTEX_INITIALIZE CAIRO_MUTEX_IMPL_INITIALIZE +#define CAIRO_MUTEX_FINALIZE CAIRO_MUTEX_IMPL_FINALIZE +#define CAIRO_MUTEX_LOCK CAIRO_MUTEX_IMPL_LOCK +#define CAIRO_MUTEX_UNLOCK CAIRO_MUTEX_IMPL_UNLOCK +#define CAIRO_MUTEX_INIT CAIRO_MUTEX_IMPL_INIT +#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI +#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER + + + +/* Debugging support */ + +#ifdef CAIRO_MUTEX_DEBUG + +# undef CAIRO_MUTEX_LOCK +# undef CAIRO_MUTEX_UNLOCK +# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_LOG_OP(mutex, "LOCK", CAIRO_MUTEX_IMPL_LOCK) +# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_LOG_OP(mutex, "UNLOCK", CAIRO_MUTEX_IMPL_UNLOCK) + +#define CAIRO_MUTEX_LOG_OP(mutex, msg, op) \ + do { cairo_mutex_t *__m = &(mutex); CAIRO_MUTEX_LOG(__m, msg); op(*__m); } while (0) + + +#include +#define CAIRO_MUTEX_LOG(mutex, msg) CAIRO_MUTEX_LOG0(mutex, CAIRO_MUTEX_DEBUG, msg) +#define CAIRO_MUTEX_LOG0(mutex, which, msg) if (mutex == &which) CAIRO_MUTEX_LOG1(mutex, which, msg) +#define CAIRO_MUTEX_LOG1(mutex, which, msg) \ + do { \ + void *buffer[10]; \ + int nptrs; \ + fprintf (stderr, "" #which " %s\n", msg); \ + nptrs = backtrace(buffer, ARRAY_LENGTH (buffer)); \ + backtrace_symbols_fd (buffer, nptrs, 2); \ + } while (0) + +#endif /* CAIRO_MUTEX_DEBUG */ #endif diff --git a/src/cairo-mutex.c b/src/cairo-mutex.c index 88aaf0d02..5149ee831 100644 --- a/src/cairo-mutex.c +++ b/src/cairo-mutex.c @@ -33,25 +33,27 @@ #include "cairoint.h" +#include "cairo-mutex-private.h" + #define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER #include "cairo-mutex-list-private.h" #undef CAIRO_MUTEX_DECLARE -#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER +#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER -# if _CAIRO_MUTEX_USE_STATIC_INITIALIZER -# define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE FALSE +# if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER +# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE # else -# define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE TRUE +# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE TRUE # endif -cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE; +cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; -# undef _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE +# undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE #endif -#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER +#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER void _cairo_mutex_initialize (void) { if (_cairo_mutex_initialized) @@ -65,7 +67,7 @@ void _cairo_mutex_initialize (void) } #endif -#if _CAIRO_MUTEX_USE_STATIC_FINALIZER +#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER void _cairo_mutex_finalize (void) { if (!_cairo_mutex_initialized)