OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/compiler_specific.h" | 5 #include "base/compiler_specific.h" |
6 #include "base/macros.h" | |
7 #include "base/synchronization/waitable_event.h" | |
6 #include "base/threading/platform_thread.h" | 8 #include "base/threading/platform_thread.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | |
7 | 10 |
8 #include "testing/gtest/include/gtest/gtest.h" | 11 #if defined(OS_WIN) |
12 #include <windows.h> | |
13 #endif | |
9 | 14 |
10 namespace base { | 15 namespace base { |
11 | 16 |
12 // Trivial tests that thread runs and doesn't crash on create and join --------- | 17 // Trivial tests that thread runs and doesn't crash on create and join --------- |
13 | 18 |
14 class TrivialThread : public PlatformThread::Delegate { | 19 class TrivialThread : public PlatformThread::Delegate { |
15 public: | 20 public: |
16 TrivialThread() : did_run_(false) {} | 21 TrivialThread() : did_run_(false) {} |
17 | 22 |
18 void ThreadMain() override { did_run_ = true; } | 23 void ThreadMain() override { did_run_ = true; } |
(...skipping 27 matching lines...) Expand all Loading... | |
46 for (size_t n = 0; n < arraysize(thread); n++) | 51 for (size_t n = 0; n < arraysize(thread); n++) |
47 PlatformThread::Join(handle[n]); | 52 PlatformThread::Join(handle[n]); |
48 for (size_t n = 0; n < arraysize(thread); n++) | 53 for (size_t n = 0; n < arraysize(thread); n++) |
49 ASSERT_TRUE(thread[n].did_run()); | 54 ASSERT_TRUE(thread[n].did_run()); |
50 } | 55 } |
51 | 56 |
52 // Tests of basic thread functions --------------------------------------------- | 57 // Tests of basic thread functions --------------------------------------------- |
53 | 58 |
54 class FunctionTestThread : public TrivialThread { | 59 class FunctionTestThread : public TrivialThread { |
55 public: | 60 public: |
56 FunctionTestThread() : thread_id_(0) {} | 61 FunctionTestThread() |
62 : thread_id_(kInvalidThreadId), | |
63 thread_started_(true, false), | |
64 terminate_thread_(true, false) {} | |
65 ~FunctionTestThread() override { | |
66 EXPECT_TRUE(terminate_thread_.IsSignaled()) | |
67 << "Need to mark thread for termination and join the underlying thread " | |
68 << "before destroying a FunctionTestThread as it owns the " | |
69 << "WaitableEvent blocking the underlying thread's main."; | |
70 } | |
57 | 71 |
72 // Grabs |thread_id_|, signals |thread_started_|, and then waits for | |
73 // |terminate_thread_| to be signaled before exiting. | |
58 void ThreadMain() override { | 74 void ThreadMain() override { |
59 thread_id_ = PlatformThread::CurrentId(); | 75 thread_id_ = PlatformThread::CurrentId(); |
76 EXPECT_NE(thread_id_, kInvalidThreadId); | |
60 PlatformThread::YieldCurrentThread(); | 77 PlatformThread::YieldCurrentThread(); |
61 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); | 78 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); |
62 | 79 |
63 // Make sure that the thread ID is the same across calls. | 80 // Make sure that the thread ID is the same across calls. |
64 EXPECT_EQ(thread_id_, PlatformThread::CurrentId()); | 81 EXPECT_EQ(thread_id_, PlatformThread::CurrentId()); |
65 | 82 |
66 TrivialThread::ThreadMain(); | 83 TrivialThread::ThreadMain(); |
84 | |
85 thread_started_.Signal(); | |
rvargas (doing something else)
2015/03/31 19:27:10
Shouldn't this be set between 76 and 77? (do we st
gab
2015/03/31 20:18:20
I guess the yield and sleep are no longer needed.
rvargas (doing something else)
2015/03/31 22:43:45
Thanks. But then I believe the name is misleading
gab
2015/04/01 01:14:39
I see, agreed, actually it's the dependency on Tri
rvargas (doing something else)
2015/04/01 02:04:55
Given that one set has explicit synchronization an
| |
86 | |
87 terminate_thread_.Wait(); | |
67 } | 88 } |
68 | 89 |
69 PlatformThreadId thread_id() const { return thread_id_; } | 90 PlatformThreadId thread_id() const { |
91 EXPECT_TRUE(thread_started_.IsSignaled()) << "Thread ID still unknown"; | |
92 return thread_id_; | |
93 } | |
94 | |
95 // Blocks until this thread is started. | |
96 void WaitForThreadStart() { thread_started_.Wait(); } | |
97 | |
98 // Mark this thread for termination (callers must then join this thread to be | |
99 // guaranteed of termination). | |
100 void MarkForTermination() { terminate_thread_.Signal(); } | |
70 | 101 |
71 private: | 102 private: |
72 PlatformThreadId thread_id_; | 103 PlatformThreadId thread_id_; |
73 | 104 |
105 mutable WaitableEvent thread_started_; | |
106 WaitableEvent terminate_thread_; | |
107 | |
74 DISALLOW_COPY_AND_ASSIGN(FunctionTestThread); | 108 DISALLOW_COPY_AND_ASSIGN(FunctionTestThread); |
75 }; | 109 }; |
76 | 110 |
77 TEST(PlatformThreadTest, Function) { | 111 TEST(PlatformThreadTest, Function) { |
78 PlatformThreadId main_thread_id = PlatformThread::CurrentId(); | 112 PlatformThreadId main_thread_id = PlatformThread::CurrentId(); |
79 | 113 |
80 FunctionTestThread thread; | 114 FunctionTestThread thread; |
81 PlatformThreadHandle handle; | 115 PlatformThreadHandle handle; |
82 | 116 |
83 ASSERT_FALSE(thread.did_run()); | 117 ASSERT_FALSE(thread.did_run()); |
84 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); | 118 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); |
85 PlatformThread::Join(handle); | 119 thread.WaitForThreadStart(); |
86 ASSERT_TRUE(thread.did_run()); | 120 ASSERT_TRUE(thread.did_run()); |
87 EXPECT_NE(thread.thread_id(), main_thread_id); | 121 EXPECT_NE(thread.thread_id(), main_thread_id); |
88 | 122 |
123 thread.MarkForTermination(); | |
124 PlatformThread::Join(handle); | |
125 | |
89 // Make sure that the thread ID is the same across calls. | 126 // Make sure that the thread ID is the same across calls. |
90 EXPECT_EQ(main_thread_id, PlatformThread::CurrentId()); | 127 EXPECT_EQ(main_thread_id, PlatformThread::CurrentId()); |
91 } | 128 } |
92 | 129 |
93 TEST(PlatformThreadTest, FunctionTimesTen) { | 130 TEST(PlatformThreadTest, FunctionTimesTen) { |
94 PlatformThreadId main_thread_id = PlatformThread::CurrentId(); | 131 PlatformThreadId main_thread_id = PlatformThread::CurrentId(); |
95 | 132 |
96 FunctionTestThread thread[10]; | 133 FunctionTestThread thread[10]; |
97 PlatformThreadHandle handle[arraysize(thread)]; | 134 PlatformThreadHandle handle[arraysize(thread)]; |
98 | 135 |
99 for (size_t n = 0; n < arraysize(thread); n++) | 136 for (size_t n = 0; n < arraysize(thread); n++) |
100 ASSERT_FALSE(thread[n].did_run()); | 137 ASSERT_FALSE(thread[n].did_run()); |
138 | |
101 for (size_t n = 0; n < arraysize(thread); n++) | 139 for (size_t n = 0; n < arraysize(thread); n++) |
102 ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n])); | 140 ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n])); |
103 for (size_t n = 0; n < arraysize(thread); n++) | 141 for (size_t n = 0; n < arraysize(thread); n++) |
104 PlatformThread::Join(handle[n]); | 142 thread[n].WaitForThreadStart(); |
143 | |
105 for (size_t n = 0; n < arraysize(thread); n++) { | 144 for (size_t n = 0; n < arraysize(thread); n++) { |
106 ASSERT_TRUE(thread[n].did_run()); | 145 ASSERT_TRUE(thread[n].did_run()); |
107 EXPECT_NE(thread[n].thread_id(), main_thread_id); | 146 EXPECT_NE(thread[n].thread_id(), main_thread_id); |
108 | 147 |
109 // Make sure no two threads get the same ID. | 148 // Make sure no two threads get the same ID. |
110 for (size_t i = 0; i < n; ++i) { | 149 for (size_t i = 0; i < n; ++i) { |
111 EXPECT_NE(thread[i].thread_id(), thread[n].thread_id()); | 150 EXPECT_NE(thread[i].thread_id(), thread[n].thread_id()); |
112 } | 151 } |
113 } | 152 } |
114 | 153 |
154 for (size_t n = 0; n < arraysize(thread); n++) | |
155 thread[n].MarkForTermination(); | |
156 for (size_t n = 0; n < arraysize(thread); n++) | |
157 PlatformThread::Join(handle[n]); | |
158 | |
115 // Make sure that the thread ID is the same across calls. | 159 // Make sure that the thread ID is the same across calls. |
116 EXPECT_EQ(main_thread_id, PlatformThread::CurrentId()); | 160 EXPECT_EQ(main_thread_id, PlatformThread::CurrentId()); |
117 } | 161 } |
118 | 162 |
163 namespace { | |
164 | |
165 const ThreadPriority kThreadPriorityTestValues[] = { | |
166 // Disable non-normal priority toggling on POSIX as it appears to be broken | |
167 // (http://crbug.com/468793). This is prefered to disabling the tests altogether | |
168 // on POSIX as it at least provides coverage for running this code under | |
169 // "normal" priority. | |
170 #if !defined(OS_POSIX) | |
171 kThreadPriority_RealtimeAudio, | |
172 kThreadPriority_Display, | |
173 kThreadPriority_Background, | |
174 #endif // !defined(OS_POSIX) | |
175 // Keep normal last to test unbackgrounding. | |
176 kThreadPriority_Normal | |
177 }; | |
178 | |
179 } // namespace | |
180 | |
181 // Test changing another thread's priority. | |
182 // NOTE: This test is partially disabled on POSIX, see note above and | |
183 // http://crbug.com/468793. | |
184 TEST(PlatformThreadTest, ThreadPriorityOtherThread) { | |
185 PlatformThreadHandle current_handle(PlatformThread::CurrentHandle()); | |
186 | |
187 // Confirm that the current thread's priority is as expected. | |
188 EXPECT_EQ(kThreadPriority_Normal, | |
189 PlatformThread::GetThreadPriority(current_handle)); | |
190 | |
191 // Create a test thread. | |
192 FunctionTestThread thread; | |
193 PlatformThreadHandle handle; | |
194 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); | |
195 thread.WaitForThreadStart(); | |
196 EXPECT_NE(thread.thread_id(), kInvalidThreadId); | |
197 EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId()); | |
198 | |
199 // New threads should get normal priority by default. | |
200 EXPECT_EQ(kThreadPriority_Normal, PlatformThread::GetThreadPriority(handle)); | |
201 | |
202 // Toggle each supported priority on the test thread and confirm it only | |
203 // affects it (and not the current thread). | |
204 for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { | |
205 SCOPED_TRACE(i); | |
206 | |
207 // Alter and verify the test thread's priority. | |
208 PlatformThread::SetThreadPriority(handle, kThreadPriorityTestValues[i]); | |
209 EXPECT_EQ(kThreadPriorityTestValues[i], | |
210 PlatformThread::GetThreadPriority(handle)); | |
211 | |
212 // Make sure the current thread was otherwise unaffected. | |
213 EXPECT_EQ(kThreadPriority_Normal, | |
214 PlatformThread::GetThreadPriority(current_handle)); | |
215 } | |
216 | |
217 thread.MarkForTermination(); | |
218 PlatformThread::Join(handle); | |
219 } | |
220 | |
221 // Test changing the current thread's priority (which has different semantics on | |
222 // some platforms). | |
223 // NOTE: This test is partially disabled on POSIX, see note above and | |
224 // http://crbug.com/468793. | |
225 TEST(PlatformThreadTest, ThreadPriorityCurrentThread) { | |
226 PlatformThreadHandle current_handle(PlatformThread::CurrentHandle()); | |
227 | |
228 // Confirm that the current thread's priority is as expected. | |
229 EXPECT_EQ(kThreadPriority_Normal, | |
230 PlatformThread::GetThreadPriority(current_handle)); | |
231 | |
232 // Create a test thread for verification purposes only. | |
233 FunctionTestThread thread; | |
234 PlatformThreadHandle handle; | |
235 ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle)); | |
236 thread.WaitForThreadStart(); | |
237 EXPECT_NE(thread.thread_id(), kInvalidThreadId); | |
238 EXPECT_NE(thread.thread_id(), PlatformThread::CurrentId()); | |
239 | |
240 // Confirm that the new thread's priority is as expected. | |
241 EXPECT_EQ(kThreadPriority_Normal, PlatformThread::GetThreadPriority(handle)); | |
242 | |
243 // Toggle each supported priority on the current thread and confirm it only | |
244 // affects it (and not the test thread). | |
245 for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) { | |
246 SCOPED_TRACE(i); | |
247 | |
248 // Alter and verify the current thread's priority. | |
249 PlatformThread::SetThreadPriority(current_handle, | |
250 kThreadPriorityTestValues[i]); | |
251 EXPECT_EQ(kThreadPriorityTestValues[i], | |
252 PlatformThread::GetThreadPriority(current_handle)); | |
253 | |
254 // Make sure the test thread was otherwise unaffected. | |
255 EXPECT_EQ(kThreadPriority_Normal, | |
256 PlatformThread::GetThreadPriority(handle)); | |
257 } | |
258 | |
259 // Restore current thread priority for follow-up tests. | |
260 PlatformThread::SetThreadPriority(current_handle, kThreadPriority_Normal); | |
261 | |
262 thread.MarkForTermination(); | |
263 PlatformThread::Join(handle); | |
264 } | |
265 | |
119 } // namespace base | 266 } // namespace base |
OLD | NEW |