michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkMutex_pthread_DEFINED michael@0: #define SkMutex_pthread_DEFINED michael@0: michael@0: /** Posix pthread_mutex based mutex. */ michael@0: michael@0: #ifdef SK_DEBUG_PTHREAD_MUTEX michael@0: #include "SkTypes.h" michael@0: #define SkDEBUGCODE_PTHREAD_MUTEX(code) code michael@0: #else michael@0: #define SkDEBUGCODE_PTHREAD_MUTEX(code) michael@0: #ifndef SkDebugf michael@0: void SkDebugf(const char format[], ...); michael@0: #endif michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: michael@0: // A SkBaseMutex is a POD structure that can be directly initialized michael@0: // at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the michael@0: // generation of a static initializer in the final machine code (and michael@0: // a corresponding static finalizer). michael@0: struct SkBaseMutex { michael@0: void acquire() { pthread_mutex_lock(&fMutex); } michael@0: void release() { pthread_mutex_unlock(&fMutex); } michael@0: pthread_mutex_t fMutex; michael@0: }; michael@0: michael@0: // A normal mutex that requires to be initialized through normal C++ construction, michael@0: // i.e. when it's a member of another class, or allocated on the heap. michael@0: class SkMutex : public SkBaseMutex { michael@0: public: michael@0: SkMutex() { michael@0: SkDEBUGCODE_PTHREAD_MUTEX(int status = )pthread_mutex_init(&fMutex, NULL); michael@0: SkDEBUGCODE_PTHREAD_MUTEX( michael@0: if (status != 0) { michael@0: print_pthread_error(status); michael@0: SkASSERT(0 == status); michael@0: } michael@0: ) michael@0: } michael@0: michael@0: ~SkMutex() { michael@0: SkDEBUGCODE_PTHREAD_MUTEX(int status = )pthread_mutex_destroy(&fMutex); michael@0: SkDEBUGCODE_PTHREAD_MUTEX( michael@0: if (status != 0) { michael@0: print_pthread_error(status); michael@0: SkASSERT(0 == status); michael@0: } michael@0: ) michael@0: } michael@0: michael@0: private: michael@0: SkMutex(const SkMutex&); michael@0: SkMutex& operator=(const SkMutex&); michael@0: michael@0: static void print_pthread_error(int status) { michael@0: switch (status) { michael@0: case 0: // success michael@0: break; michael@0: case EINVAL: michael@0: SkDebugf("pthread error [%d] EINVAL\n", status); michael@0: break; michael@0: case EBUSY: michael@0: SkDebugf("pthread error [%d] EBUSY\n", status); michael@0: break; michael@0: default: michael@0: SkDebugf("pthread error [%d] unknown\n", status); michael@0: break; michael@0: } michael@0: } michael@0: }; michael@0: michael@0: // Using POD-style initialization prevents the generation of a static initializer. michael@0: #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER } michael@0: michael@0: // Special case used when the static mutex must be available globally. michael@0: #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER } michael@0: michael@0: #endif