
正文
chromium之message_pump_win之三
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
上一篇分析MessagePumpForUI,参考chromium之message_pump_win之二
MessagePumpForIO,同MessagePumpForUI,也是要实现三个函数
// MessagePump methods:
virtual void ScheduleWork();
virtual void ScheduleDelayedWork(const Time& delayed_work_time); virtual void DoRunLoop();
先看看典型用法
第一种用法是不需要读取数据到buffer,因此所有的清理工作可以交给message pump
第二种用法是需要读取buffer,需要手动delete IOContext
第三种用法是在第二种的基础上,析构函数等待所有的IO结束
// Clients interested in receiving OS notifications when asynchronous IO
// operations complete should implement this interface and register themselves
// with the message pump.
//
// Typical use #1:
// // Use only when there are no user's buffers involved on the actual IO,
// // so that all the cleanup can be done by the message pump.
// class MyFile : public IOHandler {
// MyFile() {
// ...
// context_ = new IOContext;
// context_->handler = this;
// message_pump->RegisterIOHandler(file_, this);
// }
// ~MyFile() {
// if (pending_) {
// // By setting the handler to NULL, we're asking for this context
// // to be deleted when received, without calling back to us.
// context_->handler = NULL;
// } else {
// delete context_;
// }
// }
// virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
// DWORD error) {
// pending_ = false;
// }
// void DoSomeIo() {
// ...
// // The only buffer required for this operation is the overlapped
// // structure.
// ConnectNamedPipe(file_, &context_->overlapped);
// pending_ = true;
// }
// bool pending_;
// IOContext* context_;
// HANDLE file_;
// };
//
// Typical use #2:
// class MyFile : public IOHandler {
// MyFile() {
// ...
// message_pump->RegisterIOHandler(file_, this);
// }
// // Plus some code to make sure that this destructor is not called
// // while there are pending IO operations.
// ~MyFile() {
// }
// virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
// DWORD error) {
// ...
// delete context;
// }
// void DoSomeIo() {
// ...
// IOContext* context = new IOContext;
// // This is not used for anything. It just prevents the context from
// // being considered "abandoned".
// context->handler = this;
// ReadFile(file_, buffer, num_bytes, &read, &context->overlapped);
// }
// HANDLE file_;
// };
//
// Typical use #3:
// Same as the previous example, except that in order to deal with the
// requirement stated for the destructor, the class calls WaitForIOCompletion
// from the destructor to block until all IO finishes.
// ~MyFile() {
// while(pending_)
// message_pump->WaitForIOCompletion(INFINITE, this);
// }
//
来来来,上代码
1)have_work_ = 1;
2)通知MessagePump 工作
void MessagePumpForIO::ScheduleWork() {
if (InterlockedExchange(&have_work_, ))
return; // Someone else continued the pumping.
// Make sure the MessagePump does some work for us.
BOOL ret = PostQueuedCompletionStatus(port_, ,
reinterpret_cast<ULONG_PTR>(this),
reinterpret_cast<OVERLAPPED*>(this));
DCHECK(ret);
}
void MessagePumpForIO::ScheduleDelayedWork(const Time& delayed_work_time) {
// We know that we can't be blocked right now since this method can only be
// called on the same thread as Run, so we only need to update our record of
// how long to sleep when we do sleep.
delayed_work_time_ = delayed_work_time;
}
最后一个
void MessagePumpForIO::DoRunLoop() {
for (;;) {
// If we do any work, we may create more messages etc., and more work may
// possibly be waiting in another task group. When we (for example)
// WaitForIOCompletion(), there is a good chance there are still more
// messages waiting. On the other hand, when any of these methods return
// having done no work, then it is pretty unlikely that calling them
// again quickly will find any work to do. Finally, if they all say they
// had no work, then it is a good time to consider sleeping (waiting) for
// more work.
bool more_work_is_plausible = state_->delegate->DoWork();
if (state_->should_quit)
break;
more_work_is_plausible |= WaitForIOCompletion(, NULL);
if (state_->should_quit)
break;
more_work_is_plausible |=
state_->delegate->DoDelayedWork(&delayed_work_time_);
if (state_->should_quit)
break;
if (more_work_is_plausible)
continue;
more_work_is_plausible = state_->delegate->DoIdleWork();
if (state_->should_quit)
break;
if (more_work_is_plausible)
continue;
WaitForWork(); // Wait (sleep) until we have work to do again.
}
}






