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). 20 struct 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. 41 class SkMutex : public SkBaseMutex { 42 public: 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 63 private: 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