• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
acquireSkBaseMutex21     void acquire() {
22         SkASSERT(fOwner != pthread_self());  // SkMutex is not re-entrant
23         pthread_mutex_lock(&fMutex);
24         SkDEBUGCODE(fOwner = pthread_self();)
25     }
releaseSkBaseMutex26     void release() {
27         this->assertHeld();
28         SkDEBUGCODE(fOwner = 0;)
29         pthread_mutex_unlock(&fMutex);
30     }
assertHeldSkBaseMutex31     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:
SkMutex()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 
~SkMutex()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 
print_pthread_error(int status)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