| 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 |