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是何物,请看这里的 ...
随机推荐
- Arcgis Runtime sdk for android 授权
要下载和安装 ArcGISRuntime SDK for Android,您需要注册开发者账户,进而便拥有了访问所有功能的权限,从而实现开发和测试目的.但是,这种情况下,应用程序中的所有地图都具有水印 ...
- Twitter License for Android
1.Apache Software Foundation Apache 软件基金会 2.Apache Thrift 跨平台传输数据,Thrift与其他传输方式的比较: xml与JSON相比体积太 ...
- contact表单错误解决记录
在上篇表单验证中,过程中可谓坎坷,记录一下错误问题及解决方案. 我们用到的模板contact_form.html如下,其他urls.py自行去修改. <html> <head> ...
- mongoengine连接错误:“False is not a read preference”解决方法
问题出现: Mongoengine是一个可以操作MongoDB数据库的对象-文档映射器(Object-Document Mapper).出于工作需要,最近在使用MongoDB+Django实现一个数据 ...
- python----iter\next
1.说明:__getitem__\setitem可以迭代,它已经不被推荐了:建议使用__iter__\next. 2.python会先去检查__iter__\next然后再去检查__getitem__ ...
- Oracle 11g R2安装手册(图文教程)For Windows
1.Oracle 11g R2安装手册(图文教程)For Windows 1.下载Oracle 11g R2 for Windows版本,下载地址如下 官方网站: http://download.or ...
- 论山寨手机与Android 【12】3G时代SmartPhone BP部分
最成熟的3G网络系统,是3GPP项目组制订的WCDMA.WCDMA的网络结构,可参考Figure 12.1,其中有几个特点. 1. 反向兼容GSM/GRPS网络. 原有GSM网络的基站子系统(BSS) ...
- [11-2] adaboost理解
以二分类问题为例({-1,+1}) adaboost步骤: 1.初始化u1=(1/N,1/N,-,1/N) 2.找到h,使最小化,记该h为g:计算作为该g的权重 3.更新ui: 4.重复2,3得到T个 ...
- 【POJ】1330 Nearest Common Ancestors ——最近公共祖先(LCA)
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 18136 Accept ...
- 自己写一个strcmp函数(C++)
题目说明: 写一个函数,实现两个字符串的比较.即自己写一个strcmp函数,函数原型为int strcmp( char * p1, char * p2); 设p1指向字符串s1,p2指向字符串s2.要 ...