OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 SkSharedLock_DEFINED | 8 #ifndef SkSharedLock_DEFINED |
9 #define SkSharedLock_DEFINED | 9 #define SkSharedLock_DEFINED |
10 | 10 |
11 #include "SkAtomics.h" | 11 #include "SkAtomics.h" |
12 #include "SkSemaphore.h" | 12 #include "SkSemaphore.h" |
13 #include "SkTypes.h" | 13 #include "SkTypes.h" |
14 | 14 |
15 // This is a shared lock implementation similar to pthreads rwlocks. This implem entation is | 15 // There are two shared lock implementations one debug the other is high perform ance. They implement |
16 // cribbed from Preshing's article: | 16 // an interface similar to pthread's rwlocks. |
17 // This is a shared lock implementation similar to pthreads rwlocks. The high pe rformance | |
18 // implementation is cribbed from Preshing's article: | |
17 // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/ | 19 // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/ |
18 // | 20 // |
19 // This lock does not obey strict queue ordering. It will always alternate betwe en readers and | 21 // This lock does not obey strict queue ordering. It will always alternate betwe en readers and |
20 // a single writer. | 22 // a single writer. |
23 | |
24 #ifdef SK_DEBUG | |
mtklein
2015/09/09 18:48:12
I generally think google3's style on not indenting
| |
25 #include "SkMutex.h" | |
26 #include "SkTDArray.h" | |
27 #ifdef SK_BUILD_FOR_WIN | |
28 #include <windows.h> | |
29 class SkThreadID { | |
30 public: | |
31 SkThreadID() : fThreadID(GetCurrentThreadId()) { } | |
32 bool operator==(const SkThreadID& that) const { | |
33 return fThreadID == that.fThreadID; | |
34 } | |
35 | |
36 int64_t toInt() const { | |
37 return (int64_t)fThreadID; | |
38 } | |
39 | |
40 private: | |
41 DWORD fThreadID; | |
42 }; | |
43 #else | |
44 #include <pthread.h> | |
45 class SkThreadID { | |
mtklein
2015/09/09 18:48:12
Why don't we nest these inside SkSharedMutex as Th
| |
46 public: | |
47 SkThreadID() : fThreadID(pthread_self()) { } | |
48 bool operator==(const SkThreadID& that) const { | |
49 return fThreadID == that.fThreadID; | |
50 } | |
51 int64_t toInt() const { | |
52 return (int64_t)fThreadID; | |
53 } | |
54 private: | |
55 pthread_t fThreadID; | |
56 }; | |
57 #endif | |
58 | |
59 class SkThreadIDSet { | |
60 public: | |
61 // Returns true if threadID is in the set. | |
62 bool Find(SkThreadID threadID) const { | |
mtklein
2015/09/09 18:48:12
find, tryAdd, tryRemove, swap, count() :P
| |
63 for (auto& t : fThreadIDs) { | |
64 if (t == threadID) return true; | |
65 } | |
66 return false; | |
67 } | |
68 | |
69 // Returns true if did not already exist. | |
70 bool TryAdd(SkThreadID threadID) { | |
71 for (auto& t : fThreadIDs) { | |
72 if (t == threadID) return false; | |
73 } | |
74 fThreadIDs.append(1, &threadID); | |
75 return true; | |
76 } | |
77 // Returns true if already exists in Set. | |
78 bool TryRemove(SkThreadID threadID) { | |
79 for (int i = 0; i < fThreadIDs.count(); ++i) { | |
80 if (fThreadIDs[i] == threadID) { | |
81 fThreadIDs.remove(i); | |
82 return true; | |
83 } | |
84 } | |
85 return false; | |
86 } | |
87 | |
88 void Swap(SkThreadIDSet& other) { | |
89 fThreadIDs.swap(other.fThreadIDs); | |
90 } | |
91 | |
92 int Count() const { | |
93 return fThreadIDs.count(); | |
94 } | |
95 | |
96 private: | |
97 SkTDArray<SkThreadID> fThreadIDs; | |
98 }; | |
99 | |
21 class SkSharedMutex { | 100 class SkSharedMutex { |
22 public: | 101 public: |
23 SkSharedMutex(); | 102 SkSharedMutex(); |
24 ~SkSharedMutex(); | 103 ~SkSharedMutex(); |
25 // Acquire lock for exclusive use. | 104 // Acquire lock for exclusive use. |
26 void acquire(); | 105 void acquire(); |
27 | 106 |
28 // Release lock for exclusive use. | 107 // Release lock for exclusive use. |
29 void release(); | 108 void release(); |
30 | 109 |
31 // Fail if exclusive is not held. | 110 // Fail if exclusive is not held. |
32 #ifdef SK_DEBUG | |
33 void assertHeld() const; | 111 void assertHeld() const; |
34 #else | |
35 void assertHeld() const {} | |
36 #endif | |
37 | 112 |
38 // Acquire lock for shared use. | 113 // Acquire lock for shared use. |
39 void acquireShared(); | 114 void acquireShared(); |
40 | 115 |
41 // Release lock for shared use. | 116 // Release lock for shared use. |
42 void releaseShared(); | 117 void releaseShared(); |
43 | 118 |
44 // Fail if shared lock not held. | 119 // Fail if shared lock not held. |
45 #ifdef SK_DEBUG | |
46 void assertHeldShared() const; | 120 void assertHeldShared() const; |
121 | |
122 private: | |
123 SkThreadIDSet fCurrentShared; | |
124 SkThreadIDSet fWaitingExclusive; | |
125 SkThreadIDSet fWaitingShared; | |
126 int fSharedQueueSelect{0}; | |
127 mutable SkMutex fMu; | |
128 SkSemaphore fSharedQueue[2]; | |
129 SkSemaphore fExclusiveQueue; | |
130 }; | |
47 #else | 131 #else |
132 class SkSharedMutex { | |
133 public: | |
134 SkSharedMutex(); | |
135 ~SkSharedMutex(); | |
136 // Acquire lock for exclusive use. | |
137 void acquire(); | |
138 | |
139 // Release lock for exclusive use. | |
140 void release(); | |
141 | |
142 // Fail if exclusive is not held. | |
143 void assertHeld() const {} | |
144 | |
145 // Acquire lock for shared use. | |
146 void acquireShared(); | |
147 | |
148 // Release lock for shared use. | |
149 void releaseShared(); | |
150 | |
151 // Fail if shared lock not held. | |
48 void assertHeldShared() const {} | 152 void assertHeldShared() const {} |
49 #endif | |
50 | 153 |
51 private: | 154 private: |
52 SkAtomic<int32_t> fQueueCounts; | 155 SkAtomic<int32_t> fQueueCounts; |
mtklein
2015/09/09 18:48:11
I think I'd feel more cozy if there really were ju
| |
53 SkSemaphore fSharedQueue; | 156 SkSemaphore fSharedQueue; |
54 SkSemaphore fExclusiveQueue; | 157 SkSemaphore fExclusiveQueue; |
55 }; | 158 }; |
56 | 159 |
160 #endif // SK_DEBUG | |
161 | |
57 | 162 |
58 #endif // SkSharedLock_DEFINED | 163 #endif // SkSharedLock_DEFINED |
OLD | NEW |