0%

nbase 消息循环(一)MessagePump

MessagePump控制消息循环的开始与停止

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class BASE_EXPORT MessagePump
{
public:
class BASE_EXPORT Delegate
{
public:
virtual ~Delegate() {}
virtual bool DoWork() = 0;
virtual bool DoDelayedWork(TimeTicks *next_delayed_message_time) = 0;
virtual bool DoIdleWork() = 0;
};

MessagePump() {};
virtual ~MessagePump() {};

virtual void Run(Delegate* delegate) = 0;
virtual void Quit() = 0;
virtual void ScheduleWork() = 0;
virtual void ScheduleDelayedWork(const TimeTicks& delay_message_time) = 0;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class DefaultMessagePump : public MessagePump
{
public:

DefaultMessagePump();
virtual ~DefaultMessagePump() {}

virtual void Run(Delegate* delegate);
virtual void Quit();
virtual void ScheduleWork();
virtual void ScheduleDelayedWork(const TimeTicks& delay_message_time);

private:
void Wait();
void WaitTimeout(const TimeDelta &timeout);
void Wakeup();

WaitableEvent event_;
bool should_quit_;
TimeTicks delayed_work_time_;

DISALLOW_COPY_AND_ASSIGN(DefaultMessagePump);
};

MessagePumpRunQuit函数暴露给外部用来控制消息泵开始与停止。同时,当内部没有消息时,会调用Wait函数放弃时间片,具体是通过事件机制(WaitableEvent)实现

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void DefaultMessagePump::Run(Delegate* delegate)
{
// Quit must have been called outside of Run!
assert(should_quit_ == false);

for (;;)
{
// 任务态
bool did_work = delegate->DoWork();
if (should_quit_)
break;

did_work |= delegate->DoDelayedWork(&delayed_work_time_);
if (should_quit_)
break;

if (did_work)
continue;

// 空闲态
did_work = delegate->DoIdleWork();
if (should_quit_)
break;

if (did_work)
continue;

// 睡眠态
if (delayed_work_time_.is_null())
{
Wait();
}
else
{
TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
if (delay > TimeDelta())
WaitTimeout(delay);
else
{
// It looks like delayed_work_time_ indicates a time in the past, so we
// need to call DoDelayedWork now.
delayed_work_time_ = TimeTicks();
}
}
}

should_quit_ = false;
}

运行过程中MessagePump有三种状态

  • 任务态
    只处理Delegate的即时任务(Delegate::DoWork)以及延时任务(Delegate::DoDelayedWork
  • 空闲态
    Delegate的即时任务以及延时任务都为空时,属于空闲状态,处理闲时任务(Delegate::DoIdleWork
  • 睡眠态
    当闲时任务也为空时,调用MessagePump::Wait相关函数,放弃时间片

延时与睡眠