Chromium Code Reviews| Index: base/message_pump_win.cc |
| diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc |
| index 2b2a10e07534afcf7c7dd8de14567bd4c794d5cd..835a6bd9d3b7cf7392f4175a612b29d3943267fe 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,13 @@ bool MessagePumpForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) { |
| return true; |
| } |
| - if (item.context->handler) { |
| + if (!item.has_valid_io_context || item.context->handler) { |
|
rvargas (doing something else)
2012/08/13 18:54:12
This deserves a comment given that the first condi
alexeypa (please no reviews)
2012/08/13 20:02:23
Done, though both conditions are not redundant. Or
rvargas (doing something else)
2012/08/13 21:20:10
Thanks. What I meant is that (ignoring dereferenci
|
| 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_valid_io_context || |
| + (item.context->handler == item.handler)); |
| WillProcessIOEvent(); |
| item.handler->OnIOCompleted(item.context, item.bytes_transfered, |
| item.error); |
| @@ -577,7 +593,7 @@ bool MessagePumpForIO::GetIOItem(DWORD timeout, IOItem* item) { |
| item->bytes_transfered = 0; |
| } |
| - item->handler = reinterpret_cast<IOHandler*>(key); |
| + item->handler = KeyToHandler(key, &item->has_valid_io_context); |
| item->context = reinterpret_cast<IOContext*>(overlapped); |
| return true; |
| } |
| @@ -623,4 +639,27 @@ void MessagePumpForIO::DidProcessIOEvent() { |
| FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); |
| } |
| +// static |
| +ULONG_PTR MessagePumpForIO::HandlerToKey(IOHandler* handler, |
| + bool has_valid_io_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_valid_io_context) { |
| + key = key | 1; |
|
rvargas (doing something else)
2012/08/13 18:54:12
ouch
alexeypa (please no reviews)
2012/08/13 20:02:23
I think introducing a constant instead on the flag
rvargas (doing something else)
2012/08/13 21:20:10
yeah... I was just showing pain, not suggesting th
|
| + } |
|
rvargas (doing something else)
2012/08/13 18:54:12
nit: single line if without {}
alexeypa (please no reviews)
2012/08/13 20:02:23
Done.
|
| + return key; |
| +} |
| + |
| +// static |
| +MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( |
| + ULONG_PTR key, |
| + bool* has_valid_io_context_out) { |
|
rvargas (doing something else)
2012/08/13 18:54:12
nit: naming an out argument _out is highly atypica
alexeypa (please no reviews)
2012/08/13 20:02:23
Done.
|
| + *has_valid_io_context_out = !(key & 1); |
| + return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); |
| +} |
| + |
| } // namespace base |