| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/task_scheduler/scheduler_single_thread_task_runner_manager.h" | 5 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/synchronization/lock.h" | 9 #include "base/synchronization/lock.h" |
| 10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| 11 #include "base/task_scheduler/delayed_task_manager.h" | 11 #include "base/task_scheduler/delayed_task_manager.h" |
| 12 #include "base/task_scheduler/post_task.h" | 12 #include "base/task_scheduler/post_task.h" |
| 13 #include "base/task_scheduler/scheduler_worker_pool_params.h" | 13 #include "base/task_scheduler/scheduler_worker_pool_params.h" |
| 14 #include "base/task_scheduler/task_tracker.h" | 14 #include "base/task_scheduler/task_tracker.h" |
| 15 #include "base/task_scheduler/task_traits.h" | 15 #include "base/task_scheduler/task_traits.h" |
| 16 #include "base/test/test_timeouts.h" | 16 #include "base/test/test_timeouts.h" |
| 17 #include "base/threading/simple_thread.h" | 17 #include "base/threading/simple_thread.h" |
| 18 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 20 |
| 21 #if defined(OS_WIN) |
| 22 #include <objbase.h> |
| 23 #include <windows.h> |
| 24 |
| 25 #include "base/win/current_module.h" |
| 26 #endif |
| 27 |
| 21 namespace base { | 28 namespace base { |
| 22 namespace internal { | 29 namespace internal { |
| 23 | 30 |
| 24 namespace { | 31 namespace { |
| 25 | 32 |
| 26 enum WorkerPoolType : size_t { | 33 enum WorkerPoolType : size_t { |
| 27 BACKGROUND_WORKER_POOL = 0, | 34 BACKGROUND_WORKER_POOL = 0, |
| 28 FOREGROUND_WORKER_POOL, | 35 FOREGROUND_WORKER_POOL, |
| 29 }; | 36 }; |
| 30 | 37 |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 358 |
| 352 task_running.Wait(); | 359 task_running.Wait(); |
| 353 CallJoinFromDifferentThread join_from_different_thread( | 360 CallJoinFromDifferentThread join_from_different_thread( |
| 354 single_thread_task_runner_manager_.get()); | 361 single_thread_task_runner_manager_.get()); |
| 355 join_from_different_thread.Start(); | 362 join_from_different_thread.Start(); |
| 356 join_from_different_thread.WaitForRunToStart(); | 363 join_from_different_thread.WaitForRunToStart(); |
| 357 task_blocking.Signal(); | 364 task_blocking.Signal(); |
| 358 join_from_different_thread.Join(); | 365 join_from_different_thread.Join(); |
| 359 } | 366 } |
| 360 | 367 |
| 368 #if defined(OS_WIN) |
| 369 |
| 370 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { |
| 371 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 372 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 373 TaskTraits().WithShutdownBehavior( |
| 374 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 375 |
| 376 com_task_runner->PostTask( |
| 377 FROM_HERE, Bind([]() { |
| 378 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
| 379 if (SUCCEEDED(hr)) { |
| 380 ADD_FAILURE() << "COM STA was not initialized on this thread"; |
| 381 CoUninitialize(); |
| 382 } |
| 383 })); |
| 384 |
| 385 task_tracker_.Shutdown(); |
| 386 } |
| 387 |
| 388 namespace { |
| 389 |
| 390 const wchar_t* const kTestWindowClassName = |
| 391 L"TaskSchedulerSingleThreadTaskRunnerManagerTestWinMessageWindow"; |
| 392 |
| 393 class TaskSchedulerSingleThreadTaskRunnerManagerTestWin |
| 394 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { |
| 395 public: |
| 396 TaskSchedulerSingleThreadTaskRunnerManagerTestWin() = default; |
| 397 |
| 398 void SetUp() override { |
| 399 TaskSchedulerSingleThreadTaskRunnerManagerTest::SetUp(); |
| 400 register_class_succeeded_ = RegisterTestWindowClass(); |
| 401 ASSERT_TRUE(register_class_succeeded_); |
| 402 } |
| 403 |
| 404 void TearDown() override { |
| 405 if (register_class_succeeded_) |
| 406 ::UnregisterClass(kTestWindowClassName, CURRENT_MODULE()); |
| 407 |
| 408 TaskSchedulerSingleThreadTaskRunnerManagerTest::TearDown(); |
| 409 } |
| 410 |
| 411 HWND CreateTestWindow() { |
| 412 return CreateWindow(kTestWindowClassName, kTestWindowClassName, 0, 0, 0, 0, |
| 413 0, HWND_MESSAGE, nullptr, CURRENT_MODULE(), nullptr); |
| 414 } |
| 415 |
| 416 private: |
| 417 bool RegisterTestWindowClass() { |
| 418 WNDCLASSEX window_class = {}; |
| 419 window_class.cbSize = sizeof(window_class); |
| 420 window_class.lpfnWndProc = &::DefWindowProc; |
| 421 window_class.hInstance = CURRENT_MODULE(); |
| 422 window_class.lpszClassName = kTestWindowClassName; |
| 423 return !!::RegisterClassEx(&window_class); |
| 424 } |
| 425 |
| 426 bool register_class_succeeded_ = false; |
| 427 |
| 428 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); |
| 429 }; |
| 430 |
| 431 } // namespace |
| 432 |
| 433 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { |
| 434 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 435 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 436 TaskTraits().WithShutdownBehavior( |
| 437 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 438 HWND hwnd = nullptr; |
| 439 // HWNDs process messages on the thread that created them, so we have to |
| 440 // create them within the context of the task runner to properly simulate a |
| 441 // COM callback. |
| 442 com_task_runner->PostTask( |
| 443 FROM_HERE, |
| 444 Bind([](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, |
| 445 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, |
| 446 Unretained(this), &hwnd)); |
| 447 |
| 448 WaitableEvent wait_for_create_window( |
| 449 WaitableEvent::ResetPolicy::MANUAL, |
| 450 WaitableEvent::InitialState::NOT_SIGNALED); |
| 451 com_task_runner->PostTask( |
| 452 FROM_HERE, |
| 453 Bind(&WaitableEvent::Signal, Unretained(&wait_for_create_window))); |
| 454 wait_for_create_window.Wait(); |
| 455 |
| 456 ASSERT_NE(hwnd, nullptr); |
| 457 // If the message pump isn't running, we will hang here. This simulates how |
| 458 // COM would receive a callback with its own message HWND. |
| 459 SendMessage(hwnd, WM_USER, 0, 0); |
| 460 |
| 461 com_task_runner->PostTask( |
| 462 FROM_HERE, Bind([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd)); |
| 463 |
| 464 task_tracker_.Shutdown(); |
| 465 } |
| 466 |
| 467 #endif // defined(OS_WIN) |
| 468 |
| 361 } // namespace internal | 469 } // namespace internal |
| 362 } // namespace base | 470 } // namespace base |
| OLD | NEW |