Chromium Code Reviews| 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 |