1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef SkMutex_pthread_DEFINED 9#define SkMutex_pthread_DEFINED 10 11/** Posix pthread_mutex based mutex. */ 12 13#include <errno.h> 14#include <pthread.h> 15 16// A SkBaseMutex is a POD structure that can be directly initialized 17// at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the 18// generation of a static initializer in the final machine code (and 19// a corresponding static finalizer). 20struct SkBaseMutex { 21 void acquire() { 22 SkASSERT(fOwner != pthread_self()); // SkMutex is not re-entrant 23 pthread_mutex_lock(&fMutex); 24 SkDEBUGCODE(fOwner = pthread_self();) 25 } 26 void release() { 27 this->assertHeld(); 28 SkDEBUGCODE(fOwner = 0;) 29 pthread_mutex_unlock(&fMutex); 30 } 31 void assertHeld() { 32 SkASSERT(pthread_self() == fOwner); 33 } 34 35 pthread_mutex_t fMutex; 36 SkDEBUGCODE(pthread_t fOwner;) 37}; 38 39// A normal mutex that requires to be initialized through normal C++ construction, 40// i.e. when it's a member of another class, or allocated on the heap. 41class SkMutex : public SkBaseMutex { 42public: 43 SkMutex() { 44 SkDEBUGCODE(int status = )pthread_mutex_init(&fMutex, NULL); 45 SkDEBUGCODE( 46 if (status != 0) { 47 print_pthread_error(status); 48 SkASSERT(0 == status); 49 } 50 ) 51 } 52 53 ~SkMutex() { 54 SkDEBUGCODE(int status = )pthread_mutex_destroy(&fMutex); 55 SkDEBUGCODE( 56 if (status != 0) { 57 print_pthread_error(status); 58 SkASSERT(0 == status); 59 } 60 ) 61 } 62 63private: 64 SkMutex(const SkMutex&); 65 SkMutex& operator=(const SkMutex&); 66 67 static void print_pthread_error(int status) { 68 switch (status) { 69 case 0: // success 70 break; 71 case EINVAL: 72 SkDebugf("pthread error [%d] EINVAL\n", status); 73 break; 74 case EBUSY: 75 SkDebugf("pthread error [%d] EBUSY\n", status); 76 break; 77 default: 78 SkDebugf("pthread error [%d] unknown\n", status); 79 break; 80 } 81 } 82}; 83 84#define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, SkDEBUGCODE(0) } 85 86// Using POD-style initialization prevents the generation of a static initializer. 87#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = SK_BASE_MUTEX_INIT 88 89// Special case used when the static mutex must be available globally. 90#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = SK_BASE_MUTEX_INIT 91 92#endif 93