OLD | NEW |
| (Empty) |
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 // We use error-checking mutexes in Debug builds or normal fast mutexes in Relea
se builds. | |
17 // Debug builds get these checks for free: | |
18 // - a double acquire() from the same thread fails immediately instead of dead
locking; | |
19 // - release() checks that the mutex is being unlocked by its owner thread. | |
20 // I don't see a built-in way to implement assertHeld(), so we track that with a
n fOwner field. | |
21 | |
22 // This isn't technically portable, but on Linux and Android pthread_t is some s
ort of int, and | |
23 // on Darwin it's a pointer. So assuming pthread_self() never returns 0, it wor
ks as a sentinel. | |
24 SkDEBUGCODE(static const pthread_t kNoOwner = 0;) | |
25 | |
26 // An SkBaseMutex is a POD structure that can be directly initialized at declara
tion time with | |
27 // SK_DECLARE_STATIC_MUTEX. This avoids the generation of a static initializer i
n the final | |
28 // machine code (and a corresponding static finalizer). | |
29 struct SkBaseMutex { | |
30 void acquire() { | |
31 SkDEBUGCODE(int rc = ) pthread_mutex_lock(&fMutex); | |
32 SkASSERT(0 == rc); | |
33 SkDEBUGCODE(fOwner = pthread_self();) | |
34 } | |
35 void release() { | |
36 this->assertHeld(); // Usually redundant, but not for static mutexes on
Macs (see below). | |
37 SkDEBUGCODE(fOwner = kNoOwner;) | |
38 SkDEBUGCODE(int rc = ) pthread_mutex_unlock(&fMutex); | |
39 SkASSERT(0 == rc); | |
40 } | |
41 void assertHeld() { | |
42 SkASSERT(0 != pthread_equal(fOwner, pthread_self())); | |
43 } | |
44 | |
45 pthread_mutex_t fMutex; | |
46 SkDEBUGCODE(pthread_t fOwner;) // Read and write only when holding fMutex. | |
47 }; | |
48 | |
49 // A normal mutex that's required to be initialized through normal C++ construct
ion, | |
50 // i.e. when it's a member of another class, or allocated on the heap. | |
51 class SkMutex : public SkBaseMutex { | |
52 public: | |
53 SkMutex() { | |
54 #ifdef SK_DEBUG | |
55 pthread_mutexattr_t attr; | |
56 SkASSERT(0 == pthread_mutexattr_init(&attr)); | |
57 SkASSERT(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)
); | |
58 SkASSERT(0 == pthread_mutex_init(&fMutex, &attr)); | |
59 SkASSERT(0 == pthread_mutexattr_destroy(&attr)); | |
60 fOwner = kNoOwner; | |
61 #else | |
62 (void)pthread_mutex_init(&fMutex, NULL); | |
63 #endif | |
64 } | |
65 | |
66 ~SkMutex() { | |
67 SkDEBUGCODE(int rc = )pthread_mutex_destroy(&fMutex); | |
68 SkASSERT(0 == rc); | |
69 } | |
70 | |
71 private: | |
72 SkMutex(const SkMutex&); | |
73 SkMutex& operator=(const SkMutex&); | |
74 }; | |
75 | |
76 #if defined(SK_DEBUG) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) | |
77 // When possible we want to use error-check mutexes in Debug builds. See th
e note at the top. | |
78 #define SK_BASE_MUTEX_INIT { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER, kNoOwner
} | |
79 #elif defined(SK_DEBUG) | |
80 // Macs don't support PTHREAD_ERRORCHECK_MUTEX_INITIALIZER when targeting <1
0.7. We target 10.6. | |
81 #define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, kNoOwner } | |
82 #else | |
83 #define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER } | |
84 #endif | |
85 | |
86 // Using POD-style initialization prevents the generation of a static initialize
r. | |
87 // | |
88 // Without magic statics there are no thread safety guarantees on initialization | |
89 // of local statics (even POD). As a result, it is illegal to use | |
90 // SK_DECLARE_STATIC_MUTEX in a function. | |
91 // | |
92 // Because SkBaseMutex is not a primitive, a static SkBaseMutex cannot be | |
93 // initialized in a class with this macro. | |
94 #define SK_DECLARE_STATIC_MUTEX(name) namespace {} static SkBaseMutex name = SK_
BASE_MUTEX_INIT | |
95 | |
96 #endif | |
OLD | NEW |