message loop

  • 线程的事件处理循环
  • 每个thread至少有一个message loop
  • message loop主要处理task,依靠不同类型的message pump也可以处理其他任务,如 UI消息等
  • message loop 继承MessagePump::Delegate 实现委托接口
  • message loop 有可重入保护,一个任务未执行完,其他任务不可以开始
  • 只有当创建嵌入message pump时,才可发生可重入,如创建模态对话框,OLE函数(拖拽),打印等。
  • destruction_observers message loop 销毁时,通知此列表的对象。list结构,观察者模式
  • PostTask() 多线程调用,使task在messageloop所属线程的run()中被处理
  • DeleteSoon() ReleaseSoon() 保持变量,使之一直在消息循环中有效
  • 运行相关函数被重新封装至RunLoop类中
  • taskobservers task被处理之前和之后通知 观察者模式
  • type_ 类型 与 message pump相关
  • nestabletasksallowed_ 可重入标识
  • 两个队列 workqueue(需要被处理的task的队列), delayedworkqueue(按时间排序),
  • IncomingTaskQueue智能指针 IncomingTaskQueue批量复制到workqueue或delayedwork_queue中起到减少锁等待的作用
  • MessageLoopForUI/MessageLoopForIO 提供为pump加入(删除)观察者的接口
  • lazytlsptr 静态对象保持message loop指针

message loop proxy

  • 多线程访问message loop对象,使用proxy管理message loop生命周期
  • 返回带引用计数的message loop的智能指针
  • 相关文件 messageloopproxy.cc(h) messageloopimpl.cc(h)

message pump

  • 消息泵,派发task,处理非task任务
  • mesage loop的pump_指向message pump
  • loop按类型包含一个同类型的pump
  • 用来负责处理task以外的消息,决定task处理的时机,委托给loop处理task 委托模式
  • pump 的 run loop过程
    • DoInernalWork() 处理非task任务,如UI消息,完成端口消息
    • WaitForWork() 阻塞等待任务
    • 循环调用DoInternalWork(), DoWork(), DoDelayedWork()保证所有队列任务都可被执行
    • 每次循环检查退出标志
for (;;) {
    bool did_work = DoInternalWork();
    if (should_quit_)
        break;
    did_work |= delegate_->DoWork();
    if (should_quit_)
        break;

    TimeTicks next_time;
    did_work |= delegate_->DoDelayedWork(&next_time);
    if (should_quit_)
        break;

    if (did_work)
        continue;

    did_work = delegate_->DoIdleWork();
    if (should_quit_)
        break;

    if (did_work)
        continue;

    WaitForWork();
}
  • message loop default
    • evnet唤醒loop
    • delayedworktime 定时处理delayed work
  • message pump ozone:This class implements a message-pump for processing events from input devices Refer to MessagePump for further documentation.
  • message pump dispatcher:嵌套message loop 的消息派发相关
  • messagepumpobserver.h x11相关

windows 下 message pump的实现

            MessagePumpWin
                 |
              interit
                 |
         +---------------+
         |               |
MessagePumpForUI MessagePumpForUI
  • MessagePumpWin
    • 观察者列表 在处理消息的前后分别通知观察者,观察者模式
    • 延时任务运行时间
    • RunState 消息运行,包括消息重入的处理
  • MessagePumpForUI
    • 实现为一个传统的本地windows message pump
    • kMsgHaveWork是一个特殊消息作为一个event去唤醒sub pump处理task
    • 避免kMsgHaveWork被重复放入消息队列 检查havework变量保证
    • sub pump无task时自动挂起,有task时被自动唤醒
    • WMPAINT和WMTIMER优先级总是高于其他投递的消息(如,kMsgHaveWork)
    • DoRunLoop() 消息泵,相当于
while(GetMessage(&Msg,NULL, 0, 0) > 0) 
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg); 
}
  • WndProcThunk() 消息处理函数
    • MessagePumpForIO
  • 完成端口
  • 观察者列表 在处理消息的前后分别通知观察者。观察者模式

run loop

  • 消息循环
  • 从message loop剥离,在栈上分配对象,速度更快;降低message loop的复杂度
  • _loop为message loop对象的指针
  • previousrunloop_ 上一个run loop的指针
    • BeforeRun()中push Runloop stack
    • AfterRun()中pop Runloop stack
  • 每次run前都发一个quit task目的是如果之前有message loop则退出。

线程内消息

线程内部是如何进行的。但你需要进行费时的操作时候,可以派发一个事件和回调函数给 自身线程的MessageLoop,然后MessageLoop会调度该回调函数以执行其操作。问题是这有必要 吗?直接调用不就可以吗?答案是不可以,或者说是最好不要这么做,其原因在于,如果当前的 MessageLoop里面有优先级更高的事件和任务需要处理时,你这样做会阻碍它们的执行。

参考

理解WebKit和Chromium: 消息循环(Message Loop) Chrome学习笔记(一):线程模型,消息循环 理解WebKit和Chromium_ Chromium的多线程机制

标签: chromium
日期: 2014-08-29 17:30:06, 10 years and 140 days ago

task

  • base/pending_task.cc(h)
  • 继承自tracking info track info相关说明位于文件tracked_object.h中
  • task为任务
  • posted_from 位置
    • Location 位于base/location.h(cc)
  • 重载小于操作符,根据时间戳和sequence_num比较任务优先级

    task queue

  • incomingtaskqueue - 任务队列

    • 队列数据结构+锁实现
    • task的时间戳一样则用sequence_num标识予以区别
    • ReloadWorkQueue() 从incoming queue 加载 task 放入 work queue(task queue和delayed task queue)
  • task queue 实时任务队列
  • delayed task queue 延时任务队列
标签: chromium
日期: 2014-08-22 17:30:06, 10 years and 147 days ago

aligned_memory

  • static存储一个类,并需要手动调用对象的构造析构函数
  • lazy instance 中使用

discardable_memory

  • 可回收内存,用于缓存大对象而不用担心内存不足的问题。
  • 当内存不足时,系统可回收已解锁的内存资源。
  • 使用listener模式,注册对内存压力进行监听。

ref_counted

  • RefCounted(Base|ThreadSafeBase) 不能作为参数被用于传递应该使用scoped_refptr
  • RefCounted
  • RefCountedThreadSafe 线程安全引用计数
  • scoped_refptr 引用计数对象的智能指针
  • RefCountedDeleteOnMessageLoop 在指定的消息循环中删除的引用计数
  • RefCountedStaticMemory
  • RefCountedBytes - std::vector实现
  • RefCountedString - std::string 实现

scoped_handle

智能 FILE 封装

scopedopenprocess

智能 进程 句柄 封装

scoped_ptr

scoper 帮助管理指针的生命周期

shared_memory

windows下用内存文件映射(file map)实现

singleton

单例模式

weak ptr

  • weak pointers 指向一个对象,此对象被多个对象拥有,其中一个拥有者释放了此对象, 其他拥有者能正常运行。
  • 通过工厂类获取(WeakPtrFactory), 工厂类包含一个拥有者(WeakReferenceOwner), 拥有者包含一个智能指针和一个是否有效标志
标签: chromium
日期: 2014-08-15 17:30:06, 10 years and 154 days ago

文档

base/callback.h中注释

作用

参数传递与函数调用分离,可异步调用 task包装callback通过message传递给另一线程执行

功能

callback本质上是对函数指针的封装,bind是把成员函数,函数等转化成callback对象。

关键对象

BindState<>由bind创建,callback保持。

产生

bind系列和callback系列都是由pump.py通过xxx.x.pump生成的。

限制

bind最多支持7个参数的函数转换。 类成员函数指针

class C;
class C {
public:
    void print(int x) {
        printf("%d\n", x);
    };
    int add(int x, int y) {
        return (x + y);
    };
};
int
main(int argc, char* argv[])
{
    C c;
    C* pc = new C();
    int (C::*add)(int,int);
    typedef void (C::*PF)(int);
    PF print = &C::print;
    add = 0;
    add = &C::add;
    int i = (c.*add)(5,6);
    (pc->*print)(i);
    return 0;
}

标签: chromium
日期: 2014-08-08 17:30:06, 10 years and 161 days ago

原文inter process communication

实现

  • windows采用命名管道
  • linux/x os 采用socketpair()
  • browser process中 I/O thread处理消息避免UI thread阻塞;view通过ChannelProxy进行消息的收发,ChannelProxy::MessageFilter 插入RenderProcessHost用于过滤资源请求类消息在I/O thread中处理
  • render process中 main render thread用于处理browser和webkit的通信,并提供同步通信机制

    消息类型

  • control message - 直接由View/ViewHost处理

  • routed message - 由View派发给注册routed的对象处理
  • View message - 发送给RenderView的消息
  • ViewHost message - 发送给RenderViewHost的消息
  • PluginProcess - message browser process发送给plugin process的消息
  • PluginProcessHost - plugin process发送给browser process的消息

    消息声明

  • 文件 rendermessagesinternal.h

IPC_MESSAGE_ROUTED2(ViewHostMsg_MyMessage, GURL, int)
IPC_MESSAGE_CONTROL0(ViewMsg_MyMessage)
  • 参数太多则可以使用结构体包装
Send(new ViewMsg_StopFinding(routing-id));

处理消息

MyClass::OnMessageReceived(const IPC::Message& message) {
  IPC_BEGIN_MESSAGE_MAP(MyClass, message)
    // Will call OnMyMessage with the message. The parameters of the message will be unpacked for you.
    IPC_MESSAGE_HANDLER(ViewHostMsg_MyMessage, OnMyMessage)  
    ...
    IPC_MESSAGE_UNHANDLED_ERROR()  // This will throw an exception for unhandled messages.
  IPC_END_MESSAGE_MAP()
}

// This function will be called with the parameters extracted from the ViewHostMsg_MyMessage message.
MyClass::OnMyMessage(const GURL& url, int something) {
  ...
}

同步消息

IPC::SyncMessage 阻塞进程直到返回

/* 声明 */
IPC_SYNC_MESSAGE_CONTROL2_1(SomeMessage,  // Message name
                            GURL, //input_param1
                            int, //input_param2
                            std::string); //result
/* 处理 */
IPC_MESSAGE_HANDLER(MyMessage, OnMyMessage)
to the OnMessageReceived function, and write:
void RenderProcessHost::OnMyMessage(GURL input_param, std::string* result) {
  *result = input_param.spec() + " is not available";
}
标签: chromium
日期: 2014-08-01 17:30:06, 10 years and 168 days ago