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是何物,请看这里的 ...
随机推荐
- Object-c 单例模式中的 allocWithZone作用
最 近因为在ios应用开发中,考虑到一些公共方法的封装使用,就决定使用单例模式的写法了..不知道,Object-c中的单例模式的写法是否和java中的写法是否有所区别? 于是阿堂从网上一搜,发现“ O ...
- 【Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之四】使用绑定C++至Lua的自己定义类
续[Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之三]动手绑定自己定义类至Lua 之后.我们已经完毕了自己定义类至Lua的绑定.在接下来的环节,我们将使用它. 首先,我们须要确定 ...
- NLS_COMP和NLS_SORT参数
Oracle默认是采用binary进行排序,这对于例如中文的排序来说,是不恰当的.使用这两个参数可以指定排序的方法,比如拼音或是,要注意可能会引起性能问题.解决方法是使用NLSSORT函数来建立一个函 ...
- IDE idea 更换项目的JDK步骤
1.如图:
- 在ASP.NET项目中使用CKEditor
CKEditor是什么 CKEidtor是一个在线富文本编辑器,可以将让用户所见即所得的获得编辑在线文本,编辑器或自动将用户编辑的文字格式转换成html代码. 在ASP.NET工程中添加CKEdito ...
- CSS样式做圆角
我处理圆角的版本是由内置的绝对定位的四个div组成,每个div都有唯一的圆角图片作CSS Sprite操作.我们将会这样做: 是什么方式导致这项技术表现得这么了不起呢(What makes this ...
- WireShark抓包软件的使用
在大学的时候学习的计算机网络的具体的知识,也使用过wireshark去抓取一些网络的封包用来分析,但是都没能系统的写一篇博客,今天总结一下吧. wireshark介绍 wireshark的官方下载网站 ...
- PHP和C#可共用的可逆加密算法
PHP 加密用法 <?phpclass DES{ var $key; var $iv; //偏移量 function DES($key = '11001100', $i ...
- Android 判断听云是否嵌入正确
编译打包成apk之后,将apk在手机上进行安装,连接数据线,打开命令行,输入以下命令: adb logcat -v time -s NBSAgent:V 之后运行嵌入听云代码的app,进行有效的网络访 ...
- hey
<div style="height:547px;"> <!--用来保留原来的位置,如果不加的话会脱离流媒体--> <div class=" ...