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 #ifdef SK_DEBUG |
16 // cribbed from Preshing's article: | 16 #include "SkMutex.h" |
17 #include "SkTDArray.h" | |
18 #ifdef SK_BUILD_FOR_WIN | |
19 #include <windows.h> | |
20 typedef DWORD threadID_t; | |
21 static threadID_t getThreadID() { return GetCurrentThreadId(); } | |
mtklein_C
2015/09/17 19:51:42
These standalone statics are typically get_thread_
herb_g
2015/09/17 21:39:41
Done.
| |
22 #else | |
23 #include <pthread.h> | |
24 typedef pthread_t threadID_t; | |
25 static threadID_t getThreadID() { return pthread_self(); } | |
mtklein_C
2015/09/17 19:51:42
static int64_t get_thread_id() { return (int64_t)p
herb_g
2015/09/17 21:39:41
Done.
| |
26 #endif | |
27 #endif // SK_DEBUG | |
28 | |
29 // There are two shared lock implementations one debug the other is high perform ance. They implement | |
30 // an interface similar to pthread's rwlocks. | |
31 // This is a shared lock implementation similar to pthreads rwlocks. The high pe rformance | |
32 // implementation is cribbed from Preshing's article: | |
17 // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/ | 33 // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/ |
18 // | 34 // |
19 // This lock does not obey strict queue ordering. It will always alternate betwe en readers and | 35 // This lock does not obey strict queue ordering. It will always alternate betwe en readers and |
20 // a single writer. | 36 // a single writer. |
21 class SkSharedMutex { | 37 class SkSharedMutex { |
22 public: | 38 public: |
23 SkSharedMutex(); | 39 SkSharedMutex(); |
24 ~SkSharedMutex(); | 40 ~SkSharedMutex(); |
25 // Acquire lock for exclusive use. | 41 // Acquire lock for exclusive use. |
26 void acquire(); | 42 void acquire(); |
27 | 43 |
28 // Release lock for exclusive use. | 44 // Release lock for exclusive use. |
29 void release(); | 45 void release(); |
30 | 46 |
31 // Fail if exclusive is not held. | 47 // Fail if exclusive is not held. |
32 #ifdef SK_DEBUG | |
33 void assertHeld() const; | 48 void assertHeld() const; |
mtklein_C
2015/09/17 19:51:42
undo these bits?
herb_g
2015/09/17 21:39:41
Done.
| |
34 #else | |
35 void assertHeld() const {} | |
36 #endif | |
37 | 49 |
38 // Acquire lock for shared use. | 50 // Acquire lock for shared use. |
39 void acquireShared(); | 51 void acquireShared(); |
40 | 52 |
41 // Release lock for shared use. | 53 // Release lock for shared use. |
42 void releaseShared(); | 54 void releaseShared(); |
43 | 55 |
44 // Fail if shared lock not held. | 56 // Fail if shared lock not held. |
45 #ifdef SK_DEBUG | |
46 void assertHeldShared() const; | 57 void assertHeldShared() const; |
47 #else | |
48 void assertHeldShared() const {} | |
49 #endif | |
50 | 58 |
51 private: | 59 private: |
60 #ifdef SK_DEBUG | |
61 class ThreadID { | |
62 public: | |
63 ThreadID() : fThreadID(getThreadID()) { } | |
64 bool operator==(const ThreadID& that) const { return fThreadID == that.f ThreadID; } | |
65 int64_t toInt() const { return (int64_t)fThreadID; } | |
66 private: | |
67 threadID_t fThreadID; | |
68 }; | |
69 | |
70 class ThreadIDSet { | |
71 public: | |
72 // Returns true if threadID is in the set. | |
73 bool find(ThreadID threadID) const { | |
74 for (auto& t : fThreadIDs) { | |
75 if (t == threadID) return true; | |
76 } | |
77 return false; | |
78 } | |
79 | |
80 // Returns true if did not already exist. | |
81 bool tryAdd(ThreadID threadID) { | |
82 for (auto& t : fThreadIDs) { | |
83 if (t == threadID) return false; | |
84 } | |
85 fThreadIDs.append(1, &threadID); | |
86 return true; | |
87 } | |
88 // Returns true if already exists in Set. | |
89 bool tryRemove(ThreadID threadID) { | |
90 for (int i = 0; i < fThreadIDs.count(); ++i) { | |
91 if (fThreadIDs[i] == threadID) { | |
92 fThreadIDs.remove(i); | |
93 return true; | |
94 } | |
95 } | |
96 return false; | |
97 } | |
98 | |
99 void swap(ThreadIDSet& other) { | |
100 fThreadIDs.swap(other.fThreadIDs); | |
101 } | |
102 | |
103 int count() const { | |
104 return fThreadIDs.count(); | |
105 } | |
106 | |
107 private: | |
108 SkTDArray<ThreadID> fThreadIDs; | |
109 }; | |
110 | |
111 ThreadIDSet fCurrentShared; | |
112 ThreadIDSet fWaitingExclusive; | |
113 ThreadIDSet fWaitingShared; | |
114 int fSharedQueueSelect{0}; | |
115 mutable SkMutex fMu; | |
116 SkSemaphore fSharedQueue[2]; | |
117 SkSemaphore fExclusiveQueue; | |
118 #else | |
52 SkAtomic<int32_t> fQueueCounts; | 119 SkAtomic<int32_t> fQueueCounts; |
53 SkSemaphore fSharedQueue; | 120 SkSemaphore fSharedQueue; |
54 SkSemaphore fExclusiveQueue; | 121 SkSemaphore fExclusiveQueue; |
122 #endif // SK_DEBUG | |
55 }; | 123 }; |
56 | 124 |
57 | |
58 #endif // SkSharedLock_DEFINED | 125 #endif // SkSharedLock_DEFINED |
OLD | NEW |