google base 之MessagePumpForUI
base库中比较有意思就是这个类了,如同很多界面库一样,创建了一个隐藏窗口来处理需要在界面线程处理的消息,大体原理也就是需要执行task的时候发送一个自定义的消息,当窗口接收到task的时候调用保存起来的回调函数,还有的是通过把回调放在消息结构体里面
自下义的消息
// Message sent to get an additional time slice for pumping (processing) another
// task (a series of such messages creates a continuous task pump).
static const int kMsgHaveWork = WM_USER + 1;
值得注意的是,别自己定义个消息和这个消息重复了,所以比较好的习惯就是定义到wm_user+100,呵呵,不过如果遇上蛋筒的库估计还是会冲突。
void MessagePumpForUI::ScheduleWork() {
if (InterlockedExchange(&have_work_, 1))
return; // Someone else continued the pumping.
// Make sure the MessagePump does some work for us.
BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork,
reinterpret_cast<WPARAM>(this), 0);
if (ret)
return; // There was room in the Window Message queue.
// We have failed to insert a have-work message, so there is a chance that we
// will starve tasks/timers while sitting in a nested message loop. Nested
// loops only look at Windows Message queues, and don't look at *our* task
// queues, etc., so we might not get a time slice in such. :-(
// We could abort here, but the fear is that this failure mode is plausibly
// common (queue is full, of about 2000 messages), so we'll do a near-graceful
// recovery. Nested loops are pretty transient (we think), so this will
// probably be recoverable.
InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert.
UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR,
MESSAGE_LOOP_PROBLEM_MAX);
}
跟其它的不同,这里的ScheduleWork只不过是发送了一个自定义的消息,然后接收么这个消息的时候处理回调以达到deal task的目的。具体看下面代码:
// static
LRESULT CALLBACK MessagePumpForUI::WndProcThunk(
HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
switch (message) {
case kMsgHaveWork:
reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage();
break;
case WM_TIMER:
reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage();
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
红色部份,传入的参数进行处理:
void MessagePumpForUI::HandleWorkMessage() {
// If we are being called outside of the context of Run, then don't try to do
// any work. This could correspond to a MessageBox call or something of that
// sort.
if (!state_) {
// Since we handled a kMsgHaveWork message, we must still update this flag.
InterlockedExchange(&have_work_, 0);
return;
}
// Let whatever would have run had we not been putting messages in the queue
// run now. This is an attempt to make our dummy message not starve other
// messages that may be in the Windows message queue.
ProcessPumpReplacementMessage();
// Now give the delegate a chance to do some work. He'll let us know if he
// needs to do more work.
if (state_->delegate->DoWork())
ScheduleWork();
}
红色部份进行了task的处理。只是这个函数现在还理解得不透彻,暂且放着
bool MessagePumpForUI::ProcessPumpReplacementMessage() {
// When we encounter a kMsgHaveWork message, this method is called to peek
// and process a replacement message, such as a WM_PAINT or WM_TIMER. The
// goal is to make the kMsgHaveWork as non-intrusive as possible, even though
// a continuous stream of such messages are posted. This method carefully
// peeks a message while there is no chance for a kMsgHaveWork to be pending,
// then resets the have_work_ flag (allowing a replacement kMsgHaveWork to
// possibly be posted), and finally dispatches that peeked replacement. Note
// that the re-post of kMsgHaveWork may be asynchronous to this thread!!
bool have_message = false;
MSG msg;
// We should not process all window messages if we are in the context of an
// OS modal loop, i.e. in the context of a windows API call like MessageBox.
// This is to ensure that these messages are peeked out by the OS modal loop.
if (MessageLoop::current()->os_modal_loop()) {
// We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
} else {
have_message = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE;
}
DCHECK(!have_message || kMsgHaveWork != msg.message ||
msg.hwnd != message_hwnd_);
// Since we discarded a kMsgHaveWork message, we must update the flag.
int old_have_work = InterlockedExchange(&have_work_, 0);
DCHECK(old_have_work);
// We don't need a special time slice if we didn't have_message to process.
if (!have_message)
return false;
// Guarantee we'll get another time slice in the case where we go into native
// windows code. This ScheduleWork() may hurt performance a tiny bit when
// tasks appear very infrequently, but when the event queue is busy, the
// kMsgHaveWork events get (percentage wise) rarer and rarer.
ScheduleWork();
return ProcessMessageHelper(msg);
}
google base 之MessagePumpForUI的更多相关文章
- colmap编译过程中出现,无法解析的外部符号错误 “__cdecl google::base::CheckOpMessageBuilder::ForVar1(void)”
错误提示: >colmap.lib(matching.obj) : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: cl ...
- google base库之simplethread
// This is the base SimpleThread. You can derive from it and implement the // virtual Run method, or ...
- google base之IncomingTaskQueue
如同名称描述的那样,这个类就是个taskqueue,也就是任务队列,添加任务到队列,然后由MessageLoop去执行task,比较关心的函数如下: bool IncomingTaskQueue::A ...
- google base库中的WaitableEvent
这个类说白了就是对windows event的封装,没有什么特别的,常规做法,等侍另一线程无非就是等侍事件置信waitsingleobject,通知事件无非就是setevent,一看就明白,不就详解, ...
- google base之LockImpl
为了兼容不同的平台,这个类采用了impl模式,win平台通过CRITICAL_SECTION, 这样的话还是相对比较简单,具体就不详解了,不过不得不说boost的实现方式就要复杂到哪里去了,当然,好处 ...
- 谷歌 google
google Google是搜索引擎名,也是一家美国上市公司名称.Google公司于1998年9月7日以私有股份公司的形式创立,以设计并管理一个互联网的搜索引擎.Google公司的总部称作“Googl ...
- Windows平台下和跨平台的相关公共库
以下主要包含windows下公共库以及跨平台公共库: 1. google base库:google下chromium项目的跨平台公共库: 2. vc_common_src:即HP_SOCKET项目中的 ...
- Caffe+CUDA7.5+CuDNNv3+OpenCV3.0+Ubuntu14.04 配置参考文献 以及 常见编译问题总结
Caffe+CUDA7.5+CuDNNv3+OpenCV3.0+Ubuntu14.04 配置参考文献 ---- Wang Xiao Warning: Please make sure the cud ...
- web2.0最全的国外API应用集合
web2.0最全的国外API应用集合 原文地址:http://www.buguat.com/post/98.html 2.0时代,越来越多的API被大家广泛应用,如果你还不了解API是何物,请看这里的 ...
随机推荐
- 步步学LINQ to SQL:将类映射到数据库表【转】
[IT168 专稿]该系列教程描述了如何采用手动的方式映射你的对象类到数据表(而不是使用象SqlMetal这样的自动化工具)以便能够支持数据表之间的M:M关系和使用实体类的数据绑定.即使你选择使用了自 ...
- C++ 顶层 const
我的主力博客:半亩方塘 本文的主要參考来源来自于:C++ Primer 中文版(第 5 版) 第 57 面至第 58 面 1. 顶层 const 与底层 const 概念 我们知道,指针本身是一个对象 ...
- Android面试必备
好吧,说实话是自己面试被问到的和自己整理的别人的一些问题,很多问题的回答可能根据水平不同层次和深度不同,如果经常忘的话可能是还没明白原理,学习就是对对抗遗忘,现在开始复习吧: 每个面试的问题都极大的贴 ...
- 观察者模式:猫叫鼠跑人醒(C#)
本着菜鸟先飞的想法,决定把平时遇到的知识点记录下来,一来是加深理解,二来是方便以后自己查阅.当您看到我这篇文章的时候,觉得代码有哪里不足的地方,请多指教,谢谢.(命名不规范是为了加深自己的理解,多多见 ...
- blog开篇
本来是写java学习开篇的,现在就把它改为博客开篇吧. 其实一直都想着记录一下自己学习的过程,或者说是借口,一直在忙,也从重庆辗转到广州,又从广州辗转到天津了,又一个新阶段开始了,猴年马月都到了,哈哈 ...
- JSP(二)
JSTL JSTL不仅可以实现EL所不能实现的逻辑循环或者条件判断,还有强大的定制标记. 使用JSTL 需要将两个文件("jstl.jar"和"standard.jar& ...
- php中的一些编程例子
#一到一百不能被三整除的数 for($i=1;$i<=100;$i++){ if($i%3 != 0){ $arr[] = $i; }} var_dump($arr); #水仙花数for($i= ...
- java中数组与List相互转换的方法
1.List转换成为数组.(这里的List是实体是ArrayList) 调用ArrayList的toArray方法. toArray public <T> T[] toArray(T[] ...
- eclipse中使用Lombok
1.下载Lombok.jar http://projectlombok.googlecode.com/files/lombok.jar 2.运行Lombok.jar: java -jar D:\00 ...
- baidu-fex 精彩文章
7 天打造前端性能监控系统 http://fex.baidu.com/blog/2014/05/build-performance-monitor-in-7-days/ 前端自动化测试探索 http: ...