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/message_loop/message_pump_win.h" | 5 #include "base/message_loop/message_pump_win.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 | 393 |
394 // Guarantee we'll get another time slice in the case where we go into native | 394 // Guarantee we'll get another time slice in the case where we go into native |
395 // windows code. This ScheduleWork() may hurt performance a tiny bit when | 395 // windows code. This ScheduleWork() may hurt performance a tiny bit when |
396 // tasks appear very infrequently, but when the event queue is busy, the | 396 // tasks appear very infrequently, but when the event queue is busy, the |
397 // kMsgHaveWork events get (percentage wise) rarer and rarer. | 397 // kMsgHaveWork events get (percentage wise) rarer and rarer. |
398 ScheduleWork(); | 398 ScheduleWork(); |
399 return ProcessMessageHelper(msg); | 399 return ProcessMessageHelper(msg); |
400 } | 400 } |
401 | 401 |
402 //----------------------------------------------------------------------------- | 402 //----------------------------------------------------------------------------- |
403 // MessagePumpForGpu public: | |
404 | |
405 MessagePumpForGpu::MessagePumpForGpu() { | |
406 event_.Set(CreateEvent(nullptr, FALSE, FALSE, nullptr)); | |
407 } | |
408 | |
409 MessagePumpForGpu::~MessagePumpForGpu() = default; | |
410 | |
411 // static | |
412 void MessagePumpForGpu::InitFactory() { | |
413 bool init_result = MessageLoop::InitMessagePumpForUIFactory( | |
414 &MessagePumpForGpu::CreateMessagePumpForGpu); | |
415 DCHECK(init_result); | |
416 } | |
417 | |
418 // static | |
419 std::unique_ptr<MessagePump> MessagePumpForGpu::CreateMessagePumpForGpu() { | |
420 return WrapUnique<MessagePump>(new MessagePumpForGpu); | |
421 } | |
422 | |
423 void MessagePumpForGpu::ScheduleWork() { | |
424 if (InterlockedExchange(&work_state_, HAVE_WORK) != READY) | |
425 return; // Someone else continued the pumping. | |
426 | |
427 // TODO(stanisc): crbug.com/596190: Preserve for crash dump analysis. | |
428 // Remove this when the bug is fixed. | |
429 last_set_event_timeticks_ = TimeTicks::Now(); | |
430 | |
431 // Make sure the MessagePump does some work for us. | |
432 SetEvent(event_.Get()); | |
433 } | |
434 | |
435 void MessagePumpForGpu::ScheduleDelayedWork( | |
436 const TimeTicks& delayed_work_time) { | |
437 // We know that we can't be blocked right now since this method can only be | |
438 // called on the same thread as Run, so we only need to update our record of | |
439 // how long to sleep when we do sleep. | |
440 delayed_work_time_ = delayed_work_time; | |
441 } | |
442 | |
443 //----------------------------------------------------------------------------- | |
444 // MessagePumpForGpu private: | |
445 | |
446 void MessagePumpForGpu::DoRunLoop() { | |
447 while (!state_->should_quit) { | |
448 // Indicate that the loop is handling the work. | |
449 // If there is a race condition between switching to WORKING state here and | |
450 // the producer thread setting the HAVE_WORK state after exiting the wait, | |
451 // the event might remain in the signalled state. That might be less than | |
452 // optimal but wouldn't result in failing to handle the work. | |
453 InterlockedExchange(&work_state_, WORKING); | |
454 | |
455 bool more_work_is_plausible = ProcessNextMessage(); | |
456 if (state_->should_quit) | |
457 break; | |
458 | |
459 more_work_is_plausible |= state_->delegate->DoWork(); | |
460 if (state_->should_quit) | |
461 break; | |
462 | |
463 more_work_is_plausible |= | |
464 state_->delegate->DoDelayedWork(&delayed_work_time_); | |
465 if (state_->should_quit) | |
466 break; | |
467 | |
468 if (more_work_is_plausible) | |
469 continue; | |
470 | |
471 more_work_is_plausible = state_->delegate->DoIdleWork(); | |
472 if (state_->should_quit) | |
473 break; | |
474 | |
475 if (more_work_is_plausible) | |
476 continue; | |
477 | |
478 // Switch that working state to READY to indicate that the loop is | |
479 // waiting for accepting new work if it is still in WORKING state and hasn't | |
480 // been signalled. Otherwise if it is in HAVE_WORK state skip the wait | |
481 // and proceed to handing the work. | |
482 if (InterlockedCompareExchange(&work_state_, READY, WORKING) == HAVE_WORK) | |
483 continue; // Skip wait, more work was requested. | |
484 | |
485 WaitForWork(); // Wait (sleep) until we have work to do again. | |
486 } | |
487 } | |
488 | |
489 void MessagePumpForGpu::WaitForWork() { | |
490 // Wait until a message is available, up to the time needed by the timer | |
491 // manager to fire the next set of timers. | |
492 int delay; | |
493 | |
494 // The while loop handles the situation where on Windows 7 and later versions | |
495 // MsgWaitForMultipleObjectsEx might time out slightly earlier (less than one | |
496 // ms) than the specified |delay|. In that situation it is more optimal to | |
497 // just wait again rather than waste a DoRunLoop cycle. | |
498 while ((delay = GetCurrentDelay()) != 0) { | |
499 if (delay < 0) // Negative value means no timers waiting. | |
500 delay = INFINITE; | |
501 | |
502 // TODO(stanisc): crbug.com/596190: Preserve for crash dump analysis. | |
503 // Remove this when the bug is fixed. | |
504 TimeTicks wait_for_work_timeticks = TimeTicks::Now(); | |
505 debug::Alias(&wait_for_work_timeticks); | |
506 debug::Alias(&delay); | |
507 | |
508 HANDLE handle = event_.Get(); | |
509 DWORD result = | |
510 MsgWaitForMultipleObjectsEx(1, &handle, delay, QS_ALLINPUT, 0); | |
511 DCHECK_NE(WAIT_FAILED, result) << GetLastError(); | |
512 if (result != WAIT_TIMEOUT) { | |
513 // Either work or message available. | |
514 return; | |
515 } | |
516 } | |
517 } | |
518 | |
519 bool MessagePumpForGpu::ProcessNextMessage() { | |
520 MSG msg; | |
521 if (!PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) | |
522 return false; | |
523 | |
524 if (msg.message == WM_QUIT) { | |
525 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", | |
526 RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX); | |
527 // WM_QUIT messages shouldn't be received by any threads in the GPU | |
528 // process. If they are, just ignore them instead of causing threads to | |
529 // exit prematurely. | |
530 return true; | |
531 } | |
532 | |
533 TranslateMessage(&msg); | |
534 DispatchMessage(&msg); | |
535 | |
536 return true; | |
537 } | |
538 | |
539 //----------------------------------------------------------------------------- | |
540 // MessagePumpForIO public: | 403 // MessagePumpForIO public: |
541 | 404 |
542 MessagePumpForIO::IOContext::IOContext() { | 405 MessagePumpForIO::IOContext::IOContext() { |
543 memset(&overlapped, 0, sizeof(overlapped)); | 406 memset(&overlapped, 0, sizeof(overlapped)); |
544 } | 407 } |
545 | 408 |
546 MessagePumpForIO::MessagePumpForIO() { | 409 MessagePumpForIO::MessagePumpForIO() { |
547 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, | 410 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, |
548 reinterpret_cast<ULONG_PTR>(nullptr), 1)); | 411 reinterpret_cast<ULONG_PTR>(nullptr), 1)); |
549 DCHECK(port_.IsValid()); | 412 DCHECK(port_.IsValid()); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 if (!filter || it->handler == filter) { | 571 if (!filter || it->handler == filter) { |
709 *item = *it; | 572 *item = *it; |
710 completed_io_.erase(it); | 573 completed_io_.erase(it); |
711 return true; | 574 return true; |
712 } | 575 } |
713 } | 576 } |
714 return false; | 577 return false; |
715 } | 578 } |
716 | 579 |
717 } // namespace base | 580 } // namespace base |
OLD | NEW |