OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <memory> | 11 #include <memory> |
12 | 12 |
13 #include "webrtc/rtc_base/asyncinvoker.h" | 13 #include "webrtc/rtc_base/asyncinvoker.h" |
14 #include "webrtc/rtc_base/asyncudpsocket.h" | 14 #include "webrtc/rtc_base/asyncudpsocket.h" |
15 #include "webrtc/rtc_base/event.h" | 15 #include "webrtc/rtc_base/event.h" |
16 #include "webrtc/rtc_base/gunit.h" | 16 #include "webrtc/rtc_base/gunit.h" |
| 17 #include "webrtc/rtc_base/nullsocketserver.h" |
17 #include "webrtc/rtc_base/physicalsocketserver.h" | 18 #include "webrtc/rtc_base/physicalsocketserver.h" |
18 #include "webrtc/rtc_base/sigslot.h" | 19 #include "webrtc/rtc_base/sigslot.h" |
19 #include "webrtc/rtc_base/socketaddress.h" | 20 #include "webrtc/rtc_base/socketaddress.h" |
20 #include "webrtc/rtc_base/thread.h" | 21 #include "webrtc/rtc_base/thread.h" |
21 | 22 |
22 #if defined(WEBRTC_WIN) | 23 #if defined(WEBRTC_WIN) |
23 #include <comdef.h> // NOLINT | 24 #include <comdef.h> // NOLINT |
24 #endif | 25 #endif |
25 | 26 |
26 using namespace rtc; | 27 using namespace rtc; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0); | 100 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0); |
100 delete msg; | 101 delete msg; |
101 } | 102 } |
102 | 103 |
103 private: | 104 private: |
104 Socket* socket_; | 105 Socket* socket_; |
105 }; | 106 }; |
106 | 107 |
107 class CustomThread : public rtc::Thread { | 108 class CustomThread : public rtc::Thread { |
108 public: | 109 public: |
109 CustomThread() {} | 110 CustomThread() |
| 111 : Thread(std::unique_ptr<SocketServer>(new rtc::NullSocketServer())) {} |
110 virtual ~CustomThread() { Stop(); } | 112 virtual ~CustomThread() { Stop(); } |
111 bool Start() { return false; } | 113 bool Start() { return false; } |
112 | 114 |
113 bool WrapCurrent() { | 115 bool WrapCurrent() { |
114 return Thread::WrapCurrent(); | 116 return Thread::WrapCurrent(); |
115 } | 117 } |
116 void UnwrapCurrent() { | 118 void UnwrapCurrent() { |
117 Thread::UnwrapCurrent(); | 119 Thread::UnwrapCurrent(); |
118 } | 120 } |
119 }; | 121 }; |
120 | 122 |
121 | 123 |
122 // A thread that does nothing when it runs and signals an event | 124 // A thread that does nothing when it runs and signals an event |
123 // when it is destroyed. | 125 // when it is destroyed. |
124 class SignalWhenDestroyedThread : public Thread { | 126 class SignalWhenDestroyedThread : public Thread { |
125 public: | 127 public: |
126 SignalWhenDestroyedThread(Event* event) | 128 SignalWhenDestroyedThread(Event* event) |
127 : event_(event) { | 129 : Thread(std::unique_ptr<SocketServer>(new NullSocketServer())), |
128 } | 130 event_(event) {} |
129 | 131 |
130 virtual ~SignalWhenDestroyedThread() { | 132 virtual ~SignalWhenDestroyedThread() { |
131 Stop(); | 133 Stop(); |
132 event_->Set(); | 134 event_->Set(); |
133 } | 135 } |
134 | 136 |
135 virtual void Run() { | 137 virtual void Run() { |
136 // Do nothing. | 138 // Do nothing. |
137 } | 139 } |
138 | 140 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 Thread::Current()->ProcessMessages(50); | 190 Thread::Current()->ProcessMessages(50); |
189 return 24; | 191 return 24; |
190 } | 192 } |
191 }; | 193 }; |
192 | 194 |
193 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 | 195 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 |
194 TEST(ThreadTest, DISABLED_Main) { | 196 TEST(ThreadTest, DISABLED_Main) { |
195 const SocketAddress addr("127.0.0.1", 0); | 197 const SocketAddress addr("127.0.0.1", 0); |
196 | 198 |
197 // Create the messaging client on its own thread. | 199 // Create the messaging client on its own thread. |
198 Thread th1; | 200 auto th1 = Thread::CreateWithSocketServer(); |
199 Socket* socket = th1.socketserver()->CreateAsyncSocket(addr.family(), | 201 Socket* socket = |
200 SOCK_DGRAM); | 202 th1->socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM); |
201 MessageClient msg_client(&th1, socket); | 203 MessageClient msg_client(th1.get(), socket); |
202 | 204 |
203 // Create the socket client on its own thread. | 205 // Create the socket client on its own thread. |
204 Thread th2; | 206 auto th2 = Thread::CreateWithSocketServer(); |
205 AsyncSocket* asocket = | 207 AsyncSocket* asocket = |
206 th2.socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM); | 208 th2->socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM); |
207 SocketClient sock_client(asocket, addr, &th1, &msg_client); | 209 SocketClient sock_client(asocket, addr, th1.get(), &msg_client); |
208 | 210 |
209 socket->Connect(sock_client.address()); | 211 socket->Connect(sock_client.address()); |
210 | 212 |
211 th1.Start(); | 213 th1->Start(); |
212 th2.Start(); | 214 th2->Start(); |
213 | 215 |
214 // Get the messages started. | 216 // Get the messages started. |
215 th1.PostDelayed(RTC_FROM_HERE, 100, &msg_client, 0, new TestMessage(1)); | 217 th1->PostDelayed(RTC_FROM_HERE, 100, &msg_client, 0, new TestMessage(1)); |
216 | 218 |
217 // Give the clients a little while to run. | 219 // Give the clients a little while to run. |
218 // Messages will be processed at 100, 300, 500, 700, 900. | 220 // Messages will be processed at 100, 300, 500, 700, 900. |
219 Thread* th_main = Thread::Current(); | 221 Thread* th_main = Thread::Current(); |
220 th_main->ProcessMessages(1000); | 222 th_main->ProcessMessages(1000); |
221 | 223 |
222 // Stop the sending client. Give the receiver a bit longer to run, in case | 224 // Stop the sending client. Give the receiver a bit longer to run, in case |
223 // it is running on a machine that is under load (e.g. the build machine). | 225 // it is running on a machine that is under load (e.g. the build machine). |
224 th1.Stop(); | 226 th1->Stop(); |
225 th_main->ProcessMessages(200); | 227 th_main->ProcessMessages(200); |
226 th2.Stop(); | 228 th2->Stop(); |
227 | 229 |
228 // Make sure the results were correct | 230 // Make sure the results were correct |
229 EXPECT_EQ(5, msg_client.count); | 231 EXPECT_EQ(5, msg_client.count); |
230 EXPECT_EQ(34, msg_client.last); | 232 EXPECT_EQ(34, msg_client.last); |
231 EXPECT_EQ(5, sock_client.count); | 233 EXPECT_EQ(5, sock_client.count); |
232 EXPECT_EQ(55, sock_client.last); | 234 EXPECT_EQ(55, sock_client.last); |
233 } | 235 } |
234 | 236 |
235 // Test that setting thread names doesn't cause a malfunction. | 237 // Test that setting thread names doesn't cause a malfunction. |
236 // There's no easy way to verify the name was set properly at this time. | 238 // There's no easy way to verify the name was set properly at this time. |
237 TEST(ThreadTest, Names) { | 239 TEST(ThreadTest, Names) { |
238 // Default name | 240 // Default name |
239 Thread *thread; | 241 auto thread = Thread::CreateWithSocketServer(); |
240 thread = new Thread(); | |
241 EXPECT_TRUE(thread->Start()); | 242 EXPECT_TRUE(thread->Start()); |
242 thread->Stop(); | 243 thread->Stop(); |
243 delete thread; | |
244 thread = new Thread(); | |
245 // Name with no object parameter | 244 // Name with no object parameter |
| 245 thread = Thread::CreateWithSocketServer(); |
246 EXPECT_TRUE(thread->SetName("No object", nullptr)); | 246 EXPECT_TRUE(thread->SetName("No object", nullptr)); |
247 EXPECT_TRUE(thread->Start()); | 247 EXPECT_TRUE(thread->Start()); |
248 thread->Stop(); | 248 thread->Stop(); |
249 delete thread; | |
250 // Really long name | 249 // Really long name |
251 thread = new Thread(); | 250 thread = Thread::CreateWithSocketServer(); |
252 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this)); | 251 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this)); |
253 EXPECT_TRUE(thread->Start()); | 252 EXPECT_TRUE(thread->Start()); |
254 thread->Stop(); | 253 thread->Stop(); |
255 delete thread; | |
256 } | 254 } |
257 | 255 |
258 TEST(ThreadTest, Wrap) { | 256 TEST(ThreadTest, Wrap) { |
259 Thread* current_thread = Thread::Current(); | 257 Thread* current_thread = Thread::Current(); |
260 current_thread->UnwrapCurrent(); | 258 current_thread->UnwrapCurrent(); |
261 CustomThread* cthread = new CustomThread(); | 259 CustomThread* cthread = new CustomThread(); |
262 EXPECT_TRUE(cthread->WrapCurrent()); | 260 EXPECT_TRUE(cthread->WrapCurrent()); |
263 EXPECT_TRUE(cthread->RunningForTest()); | 261 EXPECT_TRUE(cthread->RunningForTest()); |
264 EXPECT_FALSE(cthread->IsOwned()); | 262 EXPECT_FALSE(cthread->IsOwned()); |
265 cthread->UnwrapCurrent(); | 263 cthread->UnwrapCurrent(); |
266 EXPECT_FALSE(cthread->RunningForTest()); | 264 EXPECT_FALSE(cthread->RunningForTest()); |
267 delete cthread; | 265 delete cthread; |
268 current_thread->WrapCurrent(); | 266 current_thread->WrapCurrent(); |
269 } | 267 } |
270 | 268 |
271 TEST(ThreadTest, Invoke) { | 269 TEST(ThreadTest, Invoke) { |
272 // Create and start the thread. | 270 // Create and start the thread. |
273 Thread thread; | 271 auto thread = Thread::CreateWithSocketServer(); |
274 thread.Start(); | 272 thread->Start(); |
275 // Try calling functors. | 273 // Try calling functors. |
276 EXPECT_EQ(42, thread.Invoke<int>(RTC_FROM_HERE, FunctorA())); | 274 EXPECT_EQ(42, thread->Invoke<int>(RTC_FROM_HERE, FunctorA())); |
277 AtomicBool called; | 275 AtomicBool called; |
278 FunctorB f2(&called); | 276 FunctorB f2(&called); |
279 thread.Invoke<void>(RTC_FROM_HERE, f2); | 277 thread->Invoke<void>(RTC_FROM_HERE, f2); |
280 EXPECT_TRUE(called.get()); | 278 EXPECT_TRUE(called.get()); |
281 // Try calling bare functions. | 279 // Try calling bare functions. |
282 struct LocalFuncs { | 280 struct LocalFuncs { |
283 static int Func1() { return 999; } | 281 static int Func1() { return 999; } |
284 static void Func2() {} | 282 static void Func2() {} |
285 }; | 283 }; |
286 EXPECT_EQ(999, thread.Invoke<int>(RTC_FROM_HERE, &LocalFuncs::Func1)); | 284 EXPECT_EQ(999, thread->Invoke<int>(RTC_FROM_HERE, &LocalFuncs::Func1)); |
287 thread.Invoke<void>(RTC_FROM_HERE, &LocalFuncs::Func2); | 285 thread->Invoke<void>(RTC_FROM_HERE, &LocalFuncs::Func2); |
288 } | 286 } |
289 | 287 |
290 // Verifies that two threads calling Invoke on each other at the same time does | 288 // Verifies that two threads calling Invoke on each other at the same time does |
291 // not deadlock. | 289 // not deadlock. |
292 TEST(ThreadTest, TwoThreadsInvokeNoDeadlock) { | 290 TEST(ThreadTest, TwoThreadsInvokeNoDeadlock) { |
293 AutoThread thread; | 291 AutoThread thread; |
294 Thread* current_thread = Thread::Current(); | 292 Thread* current_thread = Thread::Current(); |
295 ASSERT_TRUE(current_thread != nullptr); | 293 ASSERT_TRUE(current_thread != nullptr); |
296 | 294 |
297 Thread other_thread; | 295 auto other_thread = Thread::CreateWithSocketServer(); |
298 other_thread.Start(); | 296 other_thread->Start(); |
299 | 297 |
300 struct LocalFuncs { | 298 struct LocalFuncs { |
301 static void Set(bool* out) { *out = true; } | 299 static void Set(bool* out) { *out = true; } |
302 static void InvokeSet(Thread* thread, bool* out) { | 300 static void InvokeSet(Thread* thread, bool* out) { |
303 thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out)); | 301 thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out)); |
304 } | 302 } |
305 }; | 303 }; |
306 | 304 |
307 bool called = false; | 305 bool called = false; |
308 other_thread.Invoke<void>( | 306 other_thread->Invoke<void>( |
309 RTC_FROM_HERE, Bind(&LocalFuncs::InvokeSet, current_thread, &called)); | 307 RTC_FROM_HERE, Bind(&LocalFuncs::InvokeSet, current_thread, &called)); |
310 | 308 |
311 EXPECT_TRUE(called); | 309 EXPECT_TRUE(called); |
312 } | 310 } |
313 | 311 |
314 // Verifies that if thread A invokes a call on thread B and thread C is trying | 312 // Verifies that if thread A invokes a call on thread B and thread C is trying |
315 // to invoke A at the same time, thread A does not handle C's invoke while | 313 // to invoke A at the same time, thread A does not handle C's invoke while |
316 // invoking B. | 314 // invoking B. |
317 TEST(ThreadTest, ThreeThreadsInvoke) { | 315 TEST(ThreadTest, ThreeThreadsInvoke) { |
318 AutoThread thread; | 316 AutoThread thread; |
319 Thread* thread_a = Thread::Current(); | 317 Thread* thread_a = Thread::Current(); |
320 Thread thread_b, thread_c; | 318 auto thread_b = Thread::CreateWithSocketServer(); |
321 thread_b.Start(); | 319 auto thread_c = Thread::CreateWithSocketServer(); |
322 thread_c.Start(); | 320 thread_b->Start(); |
| 321 thread_c->Start(); |
323 | 322 |
324 class LockedBool { | 323 class LockedBool { |
325 public: | 324 public: |
326 explicit LockedBool(bool value) : value_(value) {} | 325 explicit LockedBool(bool value) : value_(value) {} |
327 | 326 |
328 void Set(bool value) { | 327 void Set(bool value) { |
329 CritScope lock(&crit_); | 328 CritScope lock(&crit_); |
330 value_ = value; | 329 value_ = value; |
331 } | 330 } |
332 | 331 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000); | 369 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000); |
371 } | 370 } |
372 }; | 371 }; |
373 | 372 |
374 AsyncInvoker invoker; | 373 AsyncInvoker invoker; |
375 LockedBool thread_a_called(false); | 374 LockedBool thread_a_called(false); |
376 | 375 |
377 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A. | 376 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A. |
378 // Thread B returns when C receives the call and C should be blocked until A | 377 // Thread B returns when C receives the call and C should be blocked until A |
379 // starts to process messages. | 378 // starts to process messages. |
380 thread_b.Invoke<void>(RTC_FROM_HERE, | 379 thread_b->Invoke<void>(RTC_FROM_HERE, |
381 Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker, | 380 Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker, |
382 &thread_c, thread_a, &thread_a_called)); | 381 thread_c.get(), thread_a, &thread_a_called)); |
383 EXPECT_FALSE(thread_a_called.Get()); | 382 EXPECT_FALSE(thread_a_called.Get()); |
384 | 383 |
385 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000); | 384 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000); |
386 } | 385 } |
387 | 386 |
388 // Set the name on a thread when the underlying QueueDestroyed signal is | 387 // Set the name on a thread when the underlying QueueDestroyed signal is |
389 // triggered. This causes an error if the object is already partially | 388 // triggered. This causes an error if the object is already partially |
390 // destroyed. | 389 // destroyed. |
391 class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> { | 390 class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> { |
392 public: | 391 public: |
393 SetNameOnSignalQueueDestroyedTester(Thread* thread) : thread_(thread) { | 392 SetNameOnSignalQueueDestroyedTester(Thread* thread) : thread_(thread) { |
394 thread->SignalQueueDestroyed.connect( | 393 thread->SignalQueueDestroyed.connect( |
395 this, &SetNameOnSignalQueueDestroyedTester::OnQueueDestroyed); | 394 this, &SetNameOnSignalQueueDestroyedTester::OnQueueDestroyed); |
396 } | 395 } |
397 | 396 |
398 void OnQueueDestroyed() { | 397 void OnQueueDestroyed() { |
399 // Makes sure that if we access the Thread while it's being destroyed, that | 398 // Makes sure that if we access the Thread while it's being destroyed, that |
400 // it doesn't cause a problem because the vtable has been modified. | 399 // it doesn't cause a problem because the vtable has been modified. |
401 thread_->SetName("foo", nullptr); | 400 thread_->SetName("foo", nullptr); |
402 } | 401 } |
403 | 402 |
404 private: | 403 private: |
405 Thread* thread_; | 404 Thread* thread_; |
406 }; | 405 }; |
407 | 406 |
408 TEST(ThreadTest, SetNameOnSignalQueueDestroyed) { | 407 TEST(ThreadTest, SetNameOnSignalQueueDestroyed) { |
409 Thread* thread1 = new Thread(); | 408 auto thread1 = Thread::CreateWithSocketServer(); |
410 SetNameOnSignalQueueDestroyedTester tester1(thread1); | 409 SetNameOnSignalQueueDestroyedTester tester1(thread1.get()); |
411 delete thread1; | 410 thread1.reset(); |
412 | 411 |
413 Thread* thread2 = new AutoThread(); | 412 Thread* thread2 = new AutoThread(); |
414 SetNameOnSignalQueueDestroyedTester tester2(thread2); | 413 SetNameOnSignalQueueDestroyedTester tester2(thread2); |
415 delete thread2; | 414 delete thread2; |
416 } | 415 } |
417 | 416 |
418 class AsyncInvokeTest : public testing::Test { | 417 class AsyncInvokeTest : public testing::Test { |
419 public: | 418 public: |
420 void IntCallback(int value) { | 419 void IntCallback(int value) { |
421 EXPECT_EQ(expected_thread_, Thread::Current()); | 420 EXPECT_EQ(expected_thread_, Thread::Current()); |
422 int_value_ = value; | 421 int_value_ = value; |
423 } | 422 } |
424 void SetExpectedThreadForIntCallback(Thread* thread) { | 423 void SetExpectedThreadForIntCallback(Thread* thread) { |
425 expected_thread_ = thread; | 424 expected_thread_ = thread; |
426 } | 425 } |
427 | 426 |
428 protected: | 427 protected: |
429 enum { kWaitTimeout = 1000 }; | 428 enum { kWaitTimeout = 1000 }; |
430 AsyncInvokeTest() | 429 AsyncInvokeTest() |
431 : int_value_(0), | 430 : int_value_(0), |
432 expected_thread_(nullptr) {} | 431 expected_thread_(nullptr) {} |
433 | 432 |
434 int int_value_; | 433 int int_value_; |
435 Thread* expected_thread_; | 434 Thread* expected_thread_; |
436 }; | 435 }; |
437 | 436 |
438 TEST_F(AsyncInvokeTest, FireAndForget) { | 437 TEST_F(AsyncInvokeTest, FireAndForget) { |
439 AsyncInvoker invoker; | 438 AsyncInvoker invoker; |
440 // Create and start the thread. | 439 // Create and start the thread. |
441 Thread thread; | 440 auto thread = Thread::CreateWithSocketServer(); |
442 thread.Start(); | 441 thread->Start(); |
443 // Try calling functor. | 442 // Try calling functor. |
444 AtomicBool called; | 443 AtomicBool called; |
445 invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, FunctorB(&called)); | 444 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), FunctorB(&called)); |
446 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout); | 445 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout); |
| 446 thread->Stop(); |
447 } | 447 } |
448 | 448 |
449 TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) { | 449 TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) { |
450 // Use these events to get in a state where the functor is in the middle of | 450 // Use these events to get in a state where the functor is in the middle of |
451 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE" | 451 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE" |
452 // is run. | 452 // is run. |
453 Event functor_started(false, false); | 453 Event functor_started(false, false); |
454 Event functor_continue(false, false); | 454 Event functor_continue(false, false); |
455 Event functor_finished(false, false); | 455 Event functor_finished(false, false); |
456 | 456 |
457 Thread thread; | 457 auto thread = Thread::CreateWithSocketServer(); |
458 thread.Start(); | 458 thread->Start(); |
459 volatile bool invoker_destroyed = false; | 459 volatile bool invoker_destroyed = false; |
460 { | 460 { |
461 AsyncInvoker invoker; | 461 AsyncInvoker invoker; |
462 invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, | 462 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), |
463 [&functor_started, &functor_continue, | 463 [&functor_started, &functor_continue, |
464 &functor_finished, &invoker_destroyed] { | 464 &functor_finished, &invoker_destroyed] { |
465 functor_started.Set(); | 465 functor_started.Set(); |
466 functor_continue.Wait(Event::kForever); | 466 functor_continue.Wait(Event::kForever); |
467 rtc::Thread::Current()->SleepMs(kWaitTimeout); | 467 rtc::Thread::Current()->SleepMs(kWaitTimeout); |
468 EXPECT_FALSE(invoker_destroyed); | 468 EXPECT_FALSE(invoker_destroyed); |
469 functor_finished.Set(); | 469 functor_finished.Set(); |
470 }); | 470 }); |
471 functor_started.Wait(Event::kForever); | 471 functor_started.Wait(Event::kForever); |
472 | 472 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 struct CreateInvoker { | 543 struct CreateInvoker { |
544 CreateInvoker(std::unique_ptr<GuardedAsyncInvoker>* invoker) | 544 CreateInvoker(std::unique_ptr<GuardedAsyncInvoker>* invoker) |
545 : invoker_(invoker) {} | 545 : invoker_(invoker) {} |
546 void operator()() { invoker_->reset(new GuardedAsyncInvoker()); } | 546 void operator()() { invoker_->reset(new GuardedAsyncInvoker()); } |
547 std::unique_ptr<GuardedAsyncInvoker>* invoker_; | 547 std::unique_ptr<GuardedAsyncInvoker>* invoker_; |
548 }; | 548 }; |
549 | 549 |
550 // Test that we can call AsyncInvoke<void>() after the thread died. | 550 // Test that we can call AsyncInvoke<void>() after the thread died. |
551 TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) { | 551 TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) { |
552 // Create and start the thread. | 552 // Create and start the thread. |
553 std::unique_ptr<Thread> thread(new Thread()); | 553 std::unique_ptr<Thread> thread(Thread::Create()); |
554 thread->Start(); | 554 thread->Start(); |
555 std::unique_ptr<GuardedAsyncInvoker> invoker; | 555 std::unique_ptr<GuardedAsyncInvoker> invoker; |
556 // Create the invoker on |thread|. | 556 // Create the invoker on |thread|. |
557 thread->Invoke<void>(RTC_FROM_HERE, CreateInvoker(&invoker)); | 557 thread->Invoke<void>(RTC_FROM_HERE, CreateInvoker(&invoker)); |
558 // Kill |thread|. | 558 // Kill |thread|. |
559 thread = nullptr; | 559 thread = nullptr; |
560 // Try calling functor. | 560 // Try calling functor. |
561 AtomicBool called; | 561 AtomicBool called; |
562 EXPECT_FALSE(invoker->AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called))); | 562 EXPECT_FALSE(invoker->AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called))); |
563 // With thread gone, nothing should happen. | 563 // With thread gone, nothing should happen. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 // Execute pending calls with id == 5. | 604 // Execute pending calls with id == 5. |
605 EXPECT_TRUE(invoker.Flush(5)); | 605 EXPECT_TRUE(invoker.Flush(5)); |
606 EXPECT_TRUE(flag1.get()); | 606 EXPECT_TRUE(flag1.get()); |
607 EXPECT_FALSE(flag2.get()); | 607 EXPECT_FALSE(flag2.get()); |
608 flag1 = false; | 608 flag1 = false; |
609 // Execute all pending calls. The id == 5 call should not execute again. | 609 // Execute all pending calls. The id == 5 call should not execute again. |
610 EXPECT_TRUE(invoker.Flush()); | 610 EXPECT_TRUE(invoker.Flush()); |
611 EXPECT_FALSE(flag1.get()); | 611 EXPECT_FALSE(flag1.get()); |
612 EXPECT_TRUE(flag2.get()); | 612 EXPECT_TRUE(flag2.get()); |
613 } | 613 } |
OLD | NEW |