OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/message_pump_glib.h" | 5 #include "base/message_loop/message_pump_glib.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <math.h> | 8 #include <math.h> |
9 | 9 |
10 #include <glib.h> | 10 #include <glib.h> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/posix/eintr_wrapper.h" | 13 #include "base/posix/eintr_wrapper.h" |
14 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
15 | 15 |
| 16 namespace base { |
| 17 |
16 namespace { | 18 namespace { |
17 | 19 |
18 // Return a timeout suitable for the glib loop, -1 to block forever, | 20 // Return a timeout suitable for the glib loop, -1 to block forever, |
19 // 0 to return right away, or a timeout in milliseconds from now. | 21 // 0 to return right away, or a timeout in milliseconds from now. |
20 int GetTimeIntervalMilliseconds(const base::TimeTicks& from) { | 22 int GetTimeIntervalMilliseconds(const TimeTicks& from) { |
21 if (from.is_null()) | 23 if (from.is_null()) |
22 return -1; | 24 return -1; |
23 | 25 |
24 // Be careful here. TimeDelta has a precision of microseconds, but we want a | 26 // Be careful here. TimeDelta has a precision of microseconds, but we want a |
25 // value in milliseconds. If there are 5.5ms left, should the delay be 5 or | 27 // value in milliseconds. If there are 5.5ms left, should the delay be 5 or |
26 // 6? It should be 6 to avoid executing delayed work too early. | 28 // 6? It should be 6 to avoid executing delayed work too early. |
27 int delay = static_cast<int>( | 29 int delay = static_cast<int>( |
28 ceil((from - base::TimeTicks::Now()).InMillisecondsF())); | 30 ceil((from - TimeTicks::Now()).InMillisecondsF())); |
29 | 31 |
30 // If this value is negative, then we need to run delayed work soon. | 32 // If this value is negative, then we need to run delayed work soon. |
31 return delay < 0 ? 0 : delay; | 33 return delay < 0 ? 0 : delay; |
32 } | 34 } |
33 | 35 |
34 // A brief refresher on GLib: | 36 // A brief refresher on GLib: |
35 // GLib sources have four callbacks: Prepare, Check, Dispatch and Finalize. | 37 // GLib sources have four callbacks: Prepare, Check, Dispatch and Finalize. |
36 // On each iteration of the GLib pump, it calls each source's Prepare function. | 38 // On each iteration of the GLib pump, it calls each source's Prepare function. |
37 // This function should return TRUE if it wants GLib to call its Dispatch, and | 39 // This function should return TRUE if it wants GLib to call its Dispatch, and |
38 // FALSE otherwise. It can also set a timeout in this case for the next time | 40 // FALSE otherwise. It can also set a timeout in this case for the next time |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 // after, from gtk_main_iteration. | 76 // after, from gtk_main_iteration. |
75 // | 77 // |
76 // For the GLib pump we try to follow the Windows UI pump model: | 78 // For the GLib pump we try to follow the Windows UI pump model: |
77 // - Whenever we receive a wakeup event or the timer for delayed work expires, | 79 // - Whenever we receive a wakeup event or the timer for delayed work expires, |
78 // we run DoWork and/or DoDelayedWork. That part will also run in the other | 80 // we run DoWork and/or DoDelayedWork. That part will also run in the other |
79 // event pumps. | 81 // event pumps. |
80 // - We also run DoWork, DoDelayedWork, and possibly DoIdleWork in the main | 82 // - We also run DoWork, DoDelayedWork, and possibly DoIdleWork in the main |
81 // loop, around event handling. | 83 // loop, around event handling. |
82 | 84 |
83 struct WorkSource : public GSource { | 85 struct WorkSource : public GSource { |
84 base::MessagePumpGlib* pump; | 86 MessagePumpGlib* pump; |
85 }; | 87 }; |
86 | 88 |
87 gboolean WorkSourcePrepare(GSource* source, | 89 gboolean WorkSourcePrepare(GSource* source, |
88 gint* timeout_ms) { | 90 gint* timeout_ms) { |
89 *timeout_ms = static_cast<WorkSource*>(source)->pump->HandlePrepare(); | 91 *timeout_ms = static_cast<WorkSource*>(source)->pump->HandlePrepare(); |
90 // We always return FALSE, so that our timeout is honored. If we were | 92 // We always return FALSE, so that our timeout is honored. If we were |
91 // to return TRUE, the timeout would be considered to be 0 and the poll | 93 // to return TRUE, the timeout would be considered to be 0 and the poll |
92 // would never block. Once the poll is finished, Check will be called. | 94 // would never block. Once the poll is finished, Check will be called. |
93 return FALSE; | 95 return FALSE; |
94 } | 96 } |
(...skipping 15 matching lines...) Expand all Loading... |
110 // I wish these could be const, but g_source_new wants non-const. | 112 // I wish these could be const, but g_source_new wants non-const. |
111 GSourceFuncs WorkSourceFuncs = { | 113 GSourceFuncs WorkSourceFuncs = { |
112 WorkSourcePrepare, | 114 WorkSourcePrepare, |
113 WorkSourceCheck, | 115 WorkSourceCheck, |
114 WorkSourceDispatch, | 116 WorkSourceDispatch, |
115 NULL | 117 NULL |
116 }; | 118 }; |
117 | 119 |
118 } // namespace | 120 } // namespace |
119 | 121 |
120 | |
121 namespace base { | |
122 | |
123 struct MessagePumpGlib::RunState { | 122 struct MessagePumpGlib::RunState { |
124 Delegate* delegate; | 123 Delegate* delegate; |
125 MessagePumpDispatcher* dispatcher; | 124 MessagePumpDispatcher* dispatcher; |
126 | 125 |
127 // Used to flag that the current Run() invocation should return ASAP. | 126 // Used to flag that the current Run() invocation should return ASAP. |
128 bool should_quit; | 127 bool should_quit; |
129 | 128 |
130 // Used to count how many Run() invocations are on the stack. | 129 // Used to count how many Run() invocations are on the stack. |
131 int run_depth; | 130 int run_depth; |
132 | 131 |
(...skipping 26 matching lines...) Expand all Loading... |
159 // This is needed to allow Run calls inside Dispatch. | 158 // This is needed to allow Run calls inside Dispatch. |
160 g_source_set_can_recurse(work_source_, TRUE); | 159 g_source_set_can_recurse(work_source_, TRUE); |
161 g_source_attach(work_source_, context_); | 160 g_source_attach(work_source_, context_); |
162 } | 161 } |
163 | 162 |
164 void MessagePumpGlib::RunWithDispatcher(Delegate* delegate, | 163 void MessagePumpGlib::RunWithDispatcher(Delegate* delegate, |
165 MessagePumpDispatcher* dispatcher) { | 164 MessagePumpDispatcher* dispatcher) { |
166 #ifndef NDEBUG | 165 #ifndef NDEBUG |
167 // Make sure we only run this on one thread. X/GTK only has one message pump | 166 // Make sure we only run this on one thread. X/GTK only has one message pump |
168 // so we can only have one UI loop per process. | 167 // so we can only have one UI loop per process. |
169 static base::PlatformThreadId thread_id = base::PlatformThread::CurrentId(); | 168 static PlatformThreadId thread_id = PlatformThread::CurrentId(); |
170 DCHECK(thread_id == base::PlatformThread::CurrentId()) << | 169 DCHECK(thread_id == PlatformThread::CurrentId()) << |
171 "Running MessagePumpGlib on two different threads; " | 170 "Running MessagePumpGlib on two different threads; " |
172 "this is unsupported by GLib!"; | 171 "this is unsupported by GLib!"; |
173 #endif | 172 #endif |
174 | 173 |
175 RunState state; | 174 RunState state; |
176 state.delegate = delegate; | 175 state.delegate = delegate; |
177 state.dispatcher = dispatcher; | 176 state.dispatcher = dispatcher; |
178 state.should_quit = false; | 177 state.should_quit = false; |
179 state.run_depth = state_ ? state_->run_depth + 1 : 1; | 178 state.run_depth = state_ ? state_->run_depth + 1 : 1; |
180 state.has_work = false; | 179 state.has_work = false; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 g_source_unref(work_source_); | 325 g_source_unref(work_source_); |
327 close(wakeup_pipe_read_); | 326 close(wakeup_pipe_read_); |
328 close(wakeup_pipe_write_); | 327 close(wakeup_pipe_write_); |
329 } | 328 } |
330 | 329 |
331 MessagePumpDispatcher* MessagePumpGlib::GetDispatcher() { | 330 MessagePumpDispatcher* MessagePumpGlib::GetDispatcher() { |
332 return state_ ? state_->dispatcher : NULL; | 331 return state_ ? state_->dispatcher : NULL; |
333 } | 332 } |
334 | 333 |
335 } // namespace base | 334 } // namespace base |
OLD | NEW |