| Index: base/message_pump_win.cc
|
| diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc
|
| index 2b2a10e07534afcf7c7dd8de14567bd4c794d5cd..628195bb2f5cff59b1fd665a82f494b936a8b541 100644
|
| --- a/base/message_pump_win.cc
|
| +++ b/base/message_pump_win.cc
|
| @@ -475,11 +475,26 @@ void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
|
|
|
| void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle,
|
| IOHandler* handler) {
|
| - ULONG_PTR key = reinterpret_cast<ULONG_PTR>(handler);
|
| + ULONG_PTR key = HandlerToKey(handler, true);
|
| HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1);
|
| DPCHECK(port);
|
| }
|
|
|
| +bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle,
|
| + IOHandler* handler) {
|
| + // Job object notifications use the OVERLAPPED pointer to carry the message
|
| + // data. Mark the completion key correspondingly, so we will not try to
|
| + // convert OVERLAPPED* to IOContext*.
|
| + ULONG_PTR key = HandlerToKey(handler, false);
|
| + JOBOBJECT_ASSOCIATE_COMPLETION_PORT info;
|
| + info.CompletionKey = reinterpret_cast<void*>(key);
|
| + info.CompletionPort = port_;
|
| + return SetInformationJobObject(job_handle,
|
| + JobObjectAssociateCompletionPortInformation,
|
| + &info,
|
| + sizeof(info)) != FALSE;
|
| +}
|
| +
|
| //-----------------------------------------------------------------------------
|
| // MessagePumpForIO private:
|
|
|
| @@ -546,12 +561,12 @@ bool MessagePumpForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
|
| return true;
|
| }
|
|
|
| - if (item.context->handler) {
|
| + if (!item.has_context || item.context->handler) {
|
| if (filter && item.handler != filter) {
|
| // Save this item for later
|
| completed_io_.push_back(item);
|
| } else {
|
| - DCHECK_EQ(item.context->handler, item.handler);
|
| + DCHECK(!item.has_context || (item.context->handler == item.handler));
|
| WillProcessIOEvent();
|
| item.handler->OnIOCompleted(item.context, item.bytes_transfered,
|
| item.error);
|
| @@ -577,7 +592,7 @@ bool MessagePumpForIO::GetIOItem(DWORD timeout, IOItem* item) {
|
| item->bytes_transfered = 0;
|
| }
|
|
|
| - item->handler = reinterpret_cast<IOHandler*>(key);
|
| + item->handler = KeyToHandler(key, &item->has_context);
|
| item->context = reinterpret_cast<IOContext*>(overlapped);
|
| return true;
|
| }
|
| @@ -623,4 +638,26 @@ void MessagePumpForIO::DidProcessIOEvent() {
|
| FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
|
| }
|
|
|
| +// static
|
| +ULONG_PTR MessagePumpForIO::HandlerToKey(IOHandler* handler, bool has_context) {
|
| + ULONG_PTR key = reinterpret_cast<ULONG_PTR>(handler);
|
| +
|
| + // |IOHandler| has virtual methods, so it is at least pointer-size aligned.
|
| + DCHECK((key & 1) == 0);
|
| +
|
| + // Mark the completion key as context-less.
|
| + if (!has_context) {
|
| + key = key | 1;
|
| + }
|
| + return key;
|
| +}
|
| +
|
| +// static
|
| +MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
|
| + ULONG_PTR key,
|
| + bool* has_context_out) {
|
| + *has_context_out = !(key & 1);
|
| + return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
|
| +}
|
| +
|
| } // namespace base
|
|
|