Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: base/message_loop/message_pump_win.cc

Issue 1954543002: Remove handler from MessagePumpForIO::IOContext. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@remove_observers
Patch Set: CR thestig #17 Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/message_loop/message_pump_win.h ('k') | device/serial/serial_io_handler_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 // windows code. This ScheduleWork() may hurt performance a tiny bit when 413 // windows code. This ScheduleWork() may hurt performance a tiny bit when
414 // tasks appear very infrequently, but when the event queue is busy, the 414 // tasks appear very infrequently, but when the event queue is busy, the
415 // kMsgHaveWork events get (percentage wise) rarer and rarer. 415 // kMsgHaveWork events get (percentage wise) rarer and rarer.
416 ScheduleWork(); 416 ScheduleWork();
417 return ProcessMessageHelper(msg); 417 return ProcessMessageHelper(msg);
418 } 418 }
419 419
420 //----------------------------------------------------------------------------- 420 //-----------------------------------------------------------------------------
421 // MessagePumpForIO public: 421 // MessagePumpForIO public:
422 422
423 MessagePumpForIO::IOContext::IOContext() {
424 memset(&overlapped, 0, sizeof(overlapped));
425 }
426
423 MessagePumpForIO::MessagePumpForIO() { 427 MessagePumpForIO::MessagePumpForIO() {
424 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1)); 428 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1));
425 DCHECK(port_.IsValid()); 429 DCHECK(port_.IsValid());
426 } 430 }
427 431
428 MessagePumpForIO::~MessagePumpForIO() { 432 MessagePumpForIO::~MessagePumpForIO() = default;
429 }
430 433
431 void MessagePumpForIO::ScheduleWork() { 434 void MessagePumpForIO::ScheduleWork() {
432 if (InterlockedExchange(&have_work_, 1)) 435 if (InterlockedExchange(&have_work_, 1))
433 return; // Someone else continued the pumping. 436 return; // Someone else continued the pumping.
434 437
435 // Make sure the MessagePump does some work for us. 438 // Make sure the MessagePump does some work for us.
436 BOOL ret = PostQueuedCompletionStatus(port_.Get(), 0, 439 BOOL ret = PostQueuedCompletionStatus(port_.Get(), 0,
437 reinterpret_cast<ULONG_PTR>(this), 440 reinterpret_cast<ULONG_PTR>(this),
438 reinterpret_cast<OVERLAPPED*>(this)); 441 reinterpret_cast<OVERLAPPED*>(this));
439 if (ret) 442 if (ret)
440 return; // Post worked perfectly. 443 return; // Post worked perfectly.
441 444
442 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery. 445 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery.
443 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed. 446 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed.
444 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, 447 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR,
445 MESSAGE_LOOP_PROBLEM_MAX); 448 MESSAGE_LOOP_PROBLEM_MAX);
446 state_->schedule_work_error_count++; 449 state_->schedule_work_error_count++;
447 state_->last_schedule_work_error_time = Time::Now(); 450 state_->last_schedule_work_error_time = Time::Now();
448 } 451 }
449 452
450 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 453 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
451 // We know that we can't be blocked right now since this method can only be 454 // We know that we can't be blocked right now since this method can only be
452 // called on the same thread as Run, so we only need to update our record of 455 // called on the same thread as Run, so we only need to update our record of
453 // how long to sleep when we do sleep. 456 // how long to sleep when we do sleep.
454 delayed_work_time_ = delayed_work_time; 457 delayed_work_time_ = delayed_work_time;
455 } 458 }
456 459
457 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, 460 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle,
458 IOHandler* handler) { 461 IOHandler* handler) {
459 ULONG_PTR key = HandlerToKey(handler, true); 462 HANDLE port = CreateIoCompletionPort(file_handle, port_.Get(),
460 HANDLE port = CreateIoCompletionPort(file_handle, port_.Get(), key, 1); 463 reinterpret_cast<ULONG_PTR>(handler), 1);
461 DPCHECK(port); 464 DPCHECK(port);
462 } 465 }
463 466
464 bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle, 467 bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle,
465 IOHandler* handler) { 468 IOHandler* handler) {
466 // Job object notifications use the OVERLAPPED pointer to carry the message
467 // data. Mark the completion key correspondingly, so we will not try to
468 // convert OVERLAPPED* to IOContext*.
469 ULONG_PTR key = HandlerToKey(handler, false);
470 JOBOBJECT_ASSOCIATE_COMPLETION_PORT info; 469 JOBOBJECT_ASSOCIATE_COMPLETION_PORT info;
471 info.CompletionKey = reinterpret_cast<void*>(key); 470 info.CompletionKey = handler;
472 info.CompletionPort = port_.Get(); 471 info.CompletionPort = port_.Get();
473 return SetInformationJobObject(job_handle, 472 return SetInformationJobObject(job_handle,
474 JobObjectAssociateCompletionPortInformation, 473 JobObjectAssociateCompletionPortInformation,
475 &info, 474 &info,
476 sizeof(info)) != FALSE; 475 sizeof(info)) != FALSE;
477 } 476 }
478 477
479 //----------------------------------------------------------------------------- 478 //-----------------------------------------------------------------------------
480 // MessagePumpForIO private: 479 // MessagePumpForIO private:
481 480
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 IOItem item; 534 IOItem item;
536 if (completed_io_.empty() || !MatchCompletedIOItem(filter, &item)) { 535 if (completed_io_.empty() || !MatchCompletedIOItem(filter, &item)) {
537 // We have to ask the system for another IO completion. 536 // We have to ask the system for another IO completion.
538 if (!GetIOItem(timeout, &item)) 537 if (!GetIOItem(timeout, &item))
539 return false; 538 return false;
540 539
541 if (ProcessInternalIOItem(item)) 540 if (ProcessInternalIOItem(item))
542 return true; 541 return true;
543 } 542 }
544 543
545 // If |item.has_valid_io_context| is false then |item.context| does not point 544 if (filter && item.handler != filter) {
546 // to a context structure, and so should not be dereferenced, although it may 545 // Save this item for later
547 // still hold valid non-pointer data. 546 completed_io_.push_back(item);
548 if (!item.has_valid_io_context || item.context->handler) {
549 if (filter && item.handler != filter) {
550 // Save this item for later
551 completed_io_.push_back(item);
552 } else {
553 DCHECK(!item.has_valid_io_context ||
554 (item.context->handler == item.handler));
555 item.handler->OnIOCompleted(item.context, item.bytes_transfered,
556 item.error);
557 }
558 } else { 547 } else {
559 // The handler must be gone by now, just cleanup the mess. 548 item.handler->OnIOCompleted(item.context, item.bytes_transfered,
560 delete item.context; 549 item.error);
561 } 550 }
562 return true; 551 return true;
563 } 552 }
564 553
565 // Asks the OS for another IO completion result. 554 // Asks the OS for another IO completion result.
566 bool MessagePumpForIO::GetIOItem(DWORD timeout, IOItem* item) { 555 bool MessagePumpForIO::GetIOItem(DWORD timeout, IOItem* item) {
567 memset(item, 0, sizeof(*item)); 556 memset(item, 0, sizeof(*item));
568 ULONG_PTR key = NULL; 557 ULONG_PTR key = NULL;
569 OVERLAPPED* overlapped = NULL; 558 OVERLAPPED* overlapped = NULL;
570 if (!GetQueuedCompletionStatus(port_.Get(), &item->bytes_transfered, &key, 559 if (!GetQueuedCompletionStatus(port_.Get(), &item->bytes_transfered, &key,
571 &overlapped, timeout)) { 560 &overlapped, timeout)) {
572 if (!overlapped) 561 if (!overlapped)
573 return false; // Nothing in the queue. 562 return false; // Nothing in the queue.
574 item->error = GetLastError(); 563 item->error = GetLastError();
575 item->bytes_transfered = 0; 564 item->bytes_transfered = 0;
576 } 565 }
577 566
578 item->handler = KeyToHandler(key, &item->has_valid_io_context); 567 item->handler = reinterpret_cast<IOHandler*>(key);
579 item->context = reinterpret_cast<IOContext*>(overlapped); 568 item->context = reinterpret_cast<IOContext*>(overlapped);
580 return true; 569 return true;
581 } 570 }
582 571
583 bool MessagePumpForIO::ProcessInternalIOItem(const IOItem& item) { 572 bool MessagePumpForIO::ProcessInternalIOItem(const IOItem& item) {
584 if (reinterpret_cast<void*>(this) == reinterpret_cast<void*>(item.context) && 573 if (reinterpret_cast<void*>(this) == reinterpret_cast<void*>(item.context) &&
585 reinterpret_cast<void*>(this) == reinterpret_cast<void*>(item.handler)) { 574 reinterpret_cast<void*>(this) == reinterpret_cast<void*>(item.handler)) {
586 // This is our internal completion. 575 // This is our internal completion.
587 DCHECK(!item.bytes_transfered); 576 DCHECK(!item.bytes_transfered);
588 InterlockedExchange(&have_work_, 0); 577 InterlockedExchange(&have_work_, 0);
589 return true; 578 return true;
590 } 579 }
591 return false; 580 return false;
592 } 581 }
593 582
594 // Returns a completion item that was previously received. 583 // Returns a completion item that was previously received.
595 bool MessagePumpForIO::MatchCompletedIOItem(IOHandler* filter, IOItem* item) { 584 bool MessagePumpForIO::MatchCompletedIOItem(IOHandler* filter, IOItem* item) {
596 DCHECK(!completed_io_.empty()); 585 DCHECK(!completed_io_.empty());
597 for (std::list<IOItem>::iterator it = completed_io_.begin(); 586 for (std::list<IOItem>::iterator it = completed_io_.begin();
598 it != completed_io_.end(); ++it) { 587 it != completed_io_.end(); ++it) {
599 if (!filter || it->handler == filter) { 588 if (!filter || it->handler == filter) {
600 *item = *it; 589 *item = *it;
601 completed_io_.erase(it); 590 completed_io_.erase(it);
602 return true; 591 return true;
603 } 592 }
604 } 593 }
605 return false; 594 return false;
606 } 595 }
607 596
608 // static
609 ULONG_PTR MessagePumpForIO::HandlerToKey(IOHandler* handler,
610 bool has_valid_io_context) {
611 ULONG_PTR key = reinterpret_cast<ULONG_PTR>(handler);
612
613 // |IOHandler| is at least pointer-size aligned, so the lowest two bits are
614 // always cleared. We use the lowest bit to distinguish completion keys with
615 // and without the associated |IOContext|.
616 DCHECK_EQ(key & 1, 0u);
617
618 // Mark the completion key as context-less.
619 if (!has_valid_io_context)
620 key = key | 1;
621 return key;
622 }
623
624 // static
625 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
626 ULONG_PTR key,
627 bool* has_valid_io_context) {
628 *has_valid_io_context = ((key & 1) == 0);
629 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
630 }
631
632 } // namespace base 597 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_win.h ('k') | device/serial/serial_io_handler_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698