|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #include "base/message_pump_android.h" |
|
6 |
|
7 #include <fcntl.h> |
|
8 #include <math.h> |
|
9 |
|
10 #include "base/eintr_wrapper.h" |
|
11 #include "base/lazy_instance.h" |
|
12 #include "base/logging.h" |
|
13 #include "base/platform_thread.h" |
|
14 |
|
15 namespace mozilla { |
|
16 bool ProcessNextEvent(); |
|
17 void NotifyEvent(); |
|
18 } |
|
19 |
|
20 namespace base { |
|
21 |
|
22 MessagePumpForUI::MessagePumpForUI() |
|
23 : state_(NULL) |
|
24 , pump(*this) |
|
25 { |
|
26 } |
|
27 |
|
28 MessagePumpForUI::~MessagePumpForUI() { |
|
29 } |
|
30 |
|
31 MessagePumpAndroid::MessagePumpAndroid(MessagePumpForUI &aPump) |
|
32 : pump(aPump) |
|
33 { |
|
34 } |
|
35 |
|
36 MessagePumpAndroid::~MessagePumpAndroid() |
|
37 { |
|
38 } |
|
39 |
|
40 void MessagePumpForUI::Run(Delegate* delegate) { |
|
41 RunState state; |
|
42 state.delegate = delegate; |
|
43 state.should_quit = false; |
|
44 state.run_depth = state_ ? state_->run_depth + 1 : 1; |
|
45 // We really only do a single task for each iteration of the loop. If we |
|
46 // have done something, assume there is likely something more to do. This |
|
47 // will mean that we don't block on the message pump until there was nothing |
|
48 // more to do. We also set this to true to make sure not to block on the |
|
49 // first iteration of the loop, so RunAllPending() works correctly. |
|
50 state.more_work_is_plausible = true; |
|
51 |
|
52 RunState* previous_state = state_; |
|
53 state_ = &state; |
|
54 |
|
55 // We run our own loop instead of using g_main_loop_quit in one of the |
|
56 // callbacks. This is so we only quit our own loops, and we don't quit |
|
57 // nested loops run by others. TODO(deanm): Is this what we want? |
|
58 |
|
59 while (!state_->should_quit) { |
|
60 mozilla::ProcessNextEvent(); |
|
61 if (work_scheduled) { |
|
62 work_scheduled = false; |
|
63 HandleDispatch(); |
|
64 } |
|
65 } |
|
66 |
|
67 state_ = previous_state; |
|
68 } |
|
69 |
|
70 void MessagePumpForUI::HandleDispatch() { |
|
71 // We should only ever have a single message on the wakeup pipe, since we |
|
72 // are only signaled when the queue went from empty to non-empty. The qApp |
|
73 // poll will tell us whether there was data, so this read shouldn't block. |
|
74 if (state_->should_quit) |
|
75 return; |
|
76 |
|
77 state_->more_work_is_plausible = false; |
|
78 |
|
79 if (state_->delegate->DoWork()) |
|
80 state_->more_work_is_plausible = true; |
|
81 |
|
82 if (state_->should_quit) |
|
83 return; |
|
84 |
|
85 if (state_->delegate->DoDelayedWork(&delayed_work_time_)) |
|
86 state_->more_work_is_plausible = true; |
|
87 if (state_->should_quit) |
|
88 return; |
|
89 |
|
90 // Don't do idle work if we think there are more important things |
|
91 // that we could be doing. |
|
92 if (state_->more_work_is_plausible) |
|
93 return; |
|
94 |
|
95 if (state_->delegate->DoIdleWork()) |
|
96 state_->more_work_is_plausible = true; |
|
97 if (state_->should_quit) |
|
98 return; |
|
99 } |
|
100 |
|
101 void MessagePumpForUI::Quit() { |
|
102 if (state_) { |
|
103 state_->should_quit = true; |
|
104 } else { |
|
105 NOTREACHED() << "Quit called outside Run!"; |
|
106 } |
|
107 } |
|
108 |
|
109 void MessagePumpForUI::ScheduleWork() { |
|
110 // This can be called on any thread, so we don't want to touch any state |
|
111 // variables as we would then need locks all over. This ensures that if |
|
112 // we are sleeping in a poll that we will wake up. |
|
113 work_scheduled = true; |
|
114 mozilla::NotifyEvent(); |
|
115 } |
|
116 |
|
117 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
|
118 // We need to wake up the loop in case the poll timeout needs to be |
|
119 // adjusted. This will cause us to try to do work, but that's ok. |
|
120 delayed_work_time_ = delayed_work_time; |
|
121 ScheduleWork(); |
|
122 } |
|
123 |
|
124 } // namespace base |