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