summaryrefslogtreecommitdiff
path: root/src/cairo-mutex-type-private.h
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2008-05-26 20:28:23 -0400
committerBehdad Esfahbod <behdad@behdad.org>2008-05-27 05:11:00 -0400
commit626edfc333b77604b6955c12ae111d14c174034c (patch)
tree33e029338be82c7bad56261acfda3870e85986b7 /src/cairo-mutex-type-private.h
parent07fef4f4802639a2cb16284841635d1bcc9b8e8f (diff)
downloadcairo-626edfc333b77604b6955c12ae111d14c174034c.tar.gz
[cairo-mutex] Prepare mutex infrastructure for adding mutex debugging facilities
Essentially renaming cairo-mutex-type-private.h to cairo-mutex-impl-private.h and changing all its namespace from cairo_mutex to cairo_mutex_impl. cairo-mutex-type-private.h then does all the sanity checks on the implementation that used to be in cairo-mutex-private.h. Plus, defines macros for the cairo-mutex namespace to map to the cairo-mutex-impl namespace. This extra mapping layer allows for add debugging facilities.
Diffstat (limited to 'src/cairo-mutex-type-private.h')
-rw-r--r--src/cairo-mutex-type-private.h269
1 files changed, 127 insertions, 142 deletions
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-features.h>
-CAIRO_BEGIN_DECLS
+#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
-/* 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)
+/* 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
-/* 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):
- *
- * <programlisting>
- * cairo_mutex_t _cairo_some_mutex;
- * </programlisting>
- *
- * - #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:
- *
- * <programlisting>
- * cairo_mutex_t _cairo_some_mutex;
- *
- * if (1)
- * CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- * else
- * CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- * </programlisting>
- *
- * - #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:
- *
- * <programlisting>
- * 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);
- * </programlisting>
- *
- * - 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:
- *
- * <programlisting>
- * 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);
- * </programlisting>
- *
- * - 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
- * <programlisting>
- * #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
- * </programlisting>
- *
- * - 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
- * <programlisting>
- * #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
- * </programlisting>
- *
- * - 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
+#ifdef CAIRO_MUTEX_IMPL_INIT
-/* No mutexes */
+/* 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)
- typedef int cairo_mutex_t;
+ /* and make sure we implement the above */
+# define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 1
+# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
-# 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
+#else /* no CAIRO_MUTEX_IMPL_INIT */
-#elif HAVE_PTHREAD_H /*******************************************************/
+/* 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 */
-# include <pthread.h>
+/* 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)
- typedef pthread_mutex_t cairo_mutex_t;
+#endif /* CAIRO_MUTEX_IMPL_INIT */
-# 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 /*******************************************************/
+#ifdef CAIRO_MUTEX_IMPL_FINI
-# include <windows.h>
+/* 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)
- typedef CRITICAL_SECTION cairo_mutex_t;
+ /* and make sure we implement the above */
+# define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 1
+# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
-# 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 }
+#else /* no CAIRO_MUTEX_IMPL_FINI */
-#elif defined __OS2__ /******************************************************/
+/* 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 */
-# define INCL_BASE
-# define INCL_PM
-# include <os2.h>
+/* neither do the dynamic ones. */
+# define CAIRO_MUTEX_IMPL_FINI(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
- typedef HMTX cairo_mutex_t;
+#endif /* CAIRO_MUTEX_IMPL_FINI */
-# 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 /***********************************************/
+#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
- 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
+/* 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
-#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."
+/* 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
-CAIRO_END_DECLS
+#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 <execinfo.h>
+#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