OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkMutex_pthread_DEFINED | 8 #ifndef SkMutex_pthread_DEFINED |
9 #define SkMutex_pthread_DEFINED | 9 #define SkMutex_pthread_DEFINED |
10 | 10 |
11 /** Posix pthread_mutex based mutex. */ | 11 /** Posix pthread_mutex based mutex. */ |
12 | 12 |
13 #include <errno.h> | 13 #include <errno.h> |
14 #include <pthread.h> | 14 #include <pthread.h> |
15 | 15 |
| 16 // This isn't technically portable, but on Linux and Android pthread_t is some s
ort of int, and |
| 17 // on Darwin it's a pointer. So assuming pthread_self() never returns 0, it wor
ks as a sentinel. |
| 18 SkDEBUGCODE(static const pthread_t kNoOwner = 0;) |
| 19 |
16 // A SkBaseMutex is a POD structure that can be directly initialized | 20 // A SkBaseMutex is a POD structure that can be directly initialized |
17 // at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the | 21 // at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the |
18 // generation of a static initializer in the final machine code (and | 22 // generation of a static initializer in the final machine code (and |
19 // a corresponding static finalizer). | 23 // a corresponding static finalizer). |
20 struct SkBaseMutex { | 24 struct SkBaseMutex { |
21 void acquire() { | 25 void acquire() { |
22 SkASSERT(fOwner != pthread_self()); // SkMutex is not re-entrant | 26 SkASSERT(0 == pthread_equal(fOwner, pthread_self())); // SkMutex is not
re-entrant |
23 pthread_mutex_lock(&fMutex); | 27 pthread_mutex_lock(&fMutex); |
24 SkDEBUGCODE(fOwner = pthread_self();) | 28 SkDEBUGCODE(fOwner = pthread_self();) |
25 } | 29 } |
26 void release() { | 30 void release() { |
27 this->assertHeld(); | 31 this->assertHeld(); |
28 SkDEBUGCODE(fOwner = 0;) | 32 SkDEBUGCODE(fOwner = kNoOwner;) |
29 pthread_mutex_unlock(&fMutex); | 33 pthread_mutex_unlock(&fMutex); |
30 } | 34 } |
31 void assertHeld() { | 35 void assertHeld() { |
32 SkASSERT(pthread_self() == fOwner); | 36 SkASSERT(0 != pthread_equal(fOwner, pthread_self())); |
33 } | 37 } |
34 | 38 |
35 pthread_mutex_t fMutex; | 39 pthread_mutex_t fMutex; |
36 SkDEBUGCODE(pthread_t fOwner;) | 40 SkDEBUGCODE(pthread_t fOwner;) |
37 }; | 41 }; |
38 | 42 |
39 // A normal mutex that requires to be initialized through normal C++ constructio
n, | 43 // A normal mutex that requires to be initialized through normal C++ constructio
n, |
40 // i.e. when it's a member of another class, or allocated on the heap. | 44 // i.e. when it's a member of another class, or allocated on the heap. |
41 class SkMutex : public SkBaseMutex { | 45 class SkMutex : public SkBaseMutex { |
42 public: | 46 public: |
43 SkMutex() { | 47 SkMutex() { |
44 SkDEBUGCODE(int status = )pthread_mutex_init(&fMutex, NULL); | 48 SkDEBUGCODE(int status = )pthread_mutex_init(&fMutex, NULL); |
45 SkDEBUGCODE( | 49 SkDEBUGCODE( |
46 if (status != 0) { | 50 if (status != 0) { |
47 print_pthread_error(status); | 51 print_pthread_error(status); |
48 SkASSERT(0 == status); | 52 SkASSERT(0 == status); |
49 } | 53 } |
| 54 fOwner = kNoOwner; |
50 ) | 55 ) |
51 } | 56 } |
52 | 57 |
53 ~SkMutex() { | 58 ~SkMutex() { |
54 SkDEBUGCODE(int status = )pthread_mutex_destroy(&fMutex); | 59 SkDEBUGCODE(int status = )pthread_mutex_destroy(&fMutex); |
55 SkDEBUGCODE( | 60 SkDEBUGCODE( |
56 if (status != 0) { | 61 if (status != 0) { |
57 print_pthread_error(status); | 62 print_pthread_error(status); |
58 SkASSERT(0 == status); | 63 SkASSERT(0 == status); |
59 } | 64 } |
(...skipping 23 matching lines...) Expand all Loading... |
83 | 88 |
84 #define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, SkDEBUGCODE(0) } | 89 #define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, SkDEBUGCODE(0) } |
85 | 90 |
86 // Using POD-style initialization prevents the generation of a static initialize
r. | 91 // Using POD-style initialization prevents the generation of a static initialize
r. |
87 #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = SK_BASE_MUTEX_IN
IT | 92 #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = SK_BASE_MUTEX_IN
IT |
88 | 93 |
89 // Special case used when the static mutex must be available globally. | 94 // Special case used when the static mutex must be available globally. |
90 #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = SK_BASE_MUTEX_INIT | 95 #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = SK_BASE_MUTEX_INIT |
91 | 96 |
92 #endif | 97 #endif |
OLD | NEW |