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_, 1))
    return;  // Someone else continued the pumping.

  // Make sure the MessagePump does some work for us.
  BOOL ret = PostQueuedCompletionStatus(port_, 0,
                                        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(0, 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.
  }
}

 

posted on 2018-06-23 20:50  ckelsel  阅读(283)  评论(0编辑  收藏  举报

导航