1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/message_pump_glib.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,334 @@ 1.4 +// Copyright (c) 2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/message_pump_glib.h" 1.9 + 1.10 +#include <fcntl.h> 1.11 +#include <math.h> 1.12 + 1.13 +#include <gtk/gtk.h> 1.14 +#include <glib.h> 1.15 + 1.16 +#include "base/eintr_wrapper.h" 1.17 +#include "base/logging.h" 1.18 +#include "base/platform_thread.h" 1.19 + 1.20 +namespace { 1.21 + 1.22 +// We send a byte across a pipe to wakeup the event loop. 1.23 +const char kWorkScheduled = '\0'; 1.24 + 1.25 +// Return a timeout suitable for the glib loop, -1 to block forever, 1.26 +// 0 to return right away, or a timeout in milliseconds from now. 1.27 +int GetTimeIntervalMilliseconds(const base::TimeTicks& from) { 1.28 + if (from.is_null()) 1.29 + return -1; 1.30 + 1.31 + // Be careful here. TimeDelta has a precision of microseconds, but we want a 1.32 + // value in milliseconds. If there are 5.5ms left, should the delay be 5 or 1.33 + // 6? It should be 6 to avoid executing delayed work too early. 1.34 + int delay = static_cast<int>( 1.35 + ceil((from - base::TimeTicks::Now()).InMillisecondsF())); 1.36 + 1.37 + // If this value is negative, then we need to run delayed work soon. 1.38 + return delay < 0 ? 0 : delay; 1.39 +} 1.40 + 1.41 +// A brief refresher on GLib: 1.42 +// GLib sources have four callbacks: Prepare, Check, Dispatch and Finalize. 1.43 +// On each iteration of the GLib pump, it calls each source's Prepare function. 1.44 +// This function should return TRUE if it wants GLib to call its Dispatch, and 1.45 +// FALSE otherwise. It can also set a timeout in this case for the next time 1.46 +// Prepare should be called again (it may be called sooner). 1.47 +// After the Prepare calls, GLib does a poll to check for events from the 1.48 +// system. File descriptors can be attached to the sources. The poll may block 1.49 +// if none of the Prepare calls returned TRUE. It will block indefinitely, or 1.50 +// by the minimum time returned by a source in Prepare. 1.51 +// After the poll, GLib calls Check for each source that returned FALSE 1.52 +// from Prepare. The return value of Check has the same meaning as for Prepare, 1.53 +// making Check a second chance to tell GLib we are ready for Dispatch. 1.54 +// Finally, GLib calls Dispatch for each source that is ready. If Dispatch 1.55 +// returns FALSE, GLib will destroy the source. Dispatch calls may be recursive 1.56 +// (i.e., you can call Run from them), but Prepare and Check cannot. 1.57 +// Finalize is called when the source is destroyed. 1.58 +// NOTE: It is common for subsytems to want to process pending events while 1.59 +// doing intensive work, for example the flash plugin. They usually use the 1.60 +// following pattern (recommended by the GTK docs): 1.61 +// while (gtk_events_pending()) { 1.62 +// gtk_main_iteration(); 1.63 +// } 1.64 +// 1.65 +// gtk_events_pending just calls g_main_context_pending, which does the 1.66 +// following: 1.67 +// - Call prepare on all the sources. 1.68 +// - Do the poll with a timeout of 0 (not blocking). 1.69 +// - Call check on all the sources. 1.70 +// - *Does not* call dispatch on the sources. 1.71 +// - Return true if any of prepare() or check() returned true. 1.72 +// 1.73 +// gtk_main_iteration just calls g_main_context_iteration, which does the whole 1.74 +// thing, respecting the timeout for the poll (and block, although it is 1.75 +// expected not to if gtk_events_pending returned true), and call dispatch. 1.76 +// 1.77 +// Thus it is important to only return true from prepare or check if we 1.78 +// actually have events or work to do. We also need to make sure we keep 1.79 +// internal state consistent so that if prepare/check return true when called 1.80 +// from gtk_events_pending, they will still return true when called right 1.81 +// after, from gtk_main_iteration. 1.82 +// 1.83 +// For the GLib pump we try to follow the Windows UI pump model: 1.84 +// - Whenever we receive a wakeup event or the timer for delayed work expires, 1.85 +// we run DoWork and/or DoDelayedWork. That part will also run in the other 1.86 +// event pumps. 1.87 +// - We also run DoWork, DoDelayedWork, and possibly DoIdleWork in the main 1.88 +// loop, around event handling. 1.89 + 1.90 +struct WorkSource : public GSource { 1.91 + base::MessagePumpForUI* pump; 1.92 +}; 1.93 + 1.94 +gboolean WorkSourcePrepare(GSource* source, 1.95 + gint* timeout_ms) { 1.96 + *timeout_ms = static_cast<WorkSource*>(source)->pump->HandlePrepare(); 1.97 + // We always return FALSE, so that our timeout is honored. If we were 1.98 + // to return TRUE, the timeout would be considered to be 0 and the poll 1.99 + // would never block. Once the poll is finished, Check will be called. 1.100 + return FALSE; 1.101 +} 1.102 + 1.103 +gboolean WorkSourceCheck(GSource* source) { 1.104 + // Only return TRUE if Dispatch should be called. 1.105 + return static_cast<WorkSource*>(source)->pump->HandleCheck(); 1.106 +} 1.107 + 1.108 +gboolean WorkSourceDispatch(GSource* source, 1.109 + GSourceFunc unused_func, 1.110 + gpointer unused_data) { 1.111 + 1.112 + static_cast<WorkSource*>(source)->pump->HandleDispatch(); 1.113 + // Always return TRUE so our source stays registered. 1.114 + return TRUE; 1.115 +} 1.116 + 1.117 +// I wish these could be const, but g_source_new wants non-const. 1.118 +GSourceFuncs WorkSourceFuncs = { 1.119 + WorkSourcePrepare, 1.120 + WorkSourceCheck, 1.121 + WorkSourceDispatch, 1.122 + NULL 1.123 +}; 1.124 + 1.125 +} // namespace 1.126 + 1.127 + 1.128 +namespace base { 1.129 + 1.130 +MessagePumpForUI::MessagePumpForUI() 1.131 + : state_(NULL), 1.132 + context_(g_main_context_default()), 1.133 + wakeup_gpollfd_(new GPollFD) { 1.134 + // Create our wakeup pipe, which is used to flag when work was scheduled. 1.135 + int fds[2]; 1.136 + CHECK(pipe(fds) == 0); 1.137 + wakeup_pipe_read_ = fds[0]; 1.138 + wakeup_pipe_write_ = fds[1]; 1.139 + wakeup_gpollfd_->fd = wakeup_pipe_read_; 1.140 + wakeup_gpollfd_->events = G_IO_IN; 1.141 + 1.142 + work_source_ = g_source_new(&WorkSourceFuncs, sizeof(WorkSource)); 1.143 + static_cast<WorkSource*>(work_source_)->pump = this; 1.144 + g_source_add_poll(work_source_, wakeup_gpollfd_.get()); 1.145 + // Use a low priority so that we let other events in the queue go first. 1.146 + g_source_set_priority(work_source_, G_PRIORITY_DEFAULT_IDLE); 1.147 + // This is needed to allow Run calls inside Dispatch. 1.148 + g_source_set_can_recurse(work_source_, TRUE); 1.149 + g_source_attach(work_source_, context_); 1.150 + gdk_event_handler_set(&EventDispatcher, this, NULL); 1.151 +} 1.152 + 1.153 +MessagePumpForUI::~MessagePumpForUI() { 1.154 + gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event), 1.155 + this, NULL); 1.156 + g_source_destroy(work_source_); 1.157 + g_source_unref(work_source_); 1.158 + close(wakeup_pipe_read_); 1.159 + close(wakeup_pipe_write_); 1.160 +} 1.161 + 1.162 +void MessagePumpForUI::RunWithDispatcher(Delegate* delegate, 1.163 + Dispatcher* dispatcher) { 1.164 +#ifndef NDEBUG 1.165 + // Make sure we only run this on one thread. GTK only has one message pump 1.166 + // so we can only have one UI loop per process. 1.167 + static PlatformThreadId thread_id = PlatformThread::CurrentId(); 1.168 + DCHECK(thread_id == PlatformThread::CurrentId()) << 1.169 + "Running MessagePumpForUI on two different threads; " 1.170 + "this is unsupported by GLib!"; 1.171 +#endif 1.172 + 1.173 + RunState state; 1.174 + state.delegate = delegate; 1.175 + state.dispatcher = dispatcher; 1.176 + state.should_quit = false; 1.177 + state.run_depth = state_ ? state_->run_depth + 1 : 1; 1.178 + state.has_work = false; 1.179 + 1.180 + RunState* previous_state = state_; 1.181 + state_ = &state; 1.182 + 1.183 + // We really only do a single task for each iteration of the loop. If we 1.184 + // have done something, assume there is likely something more to do. This 1.185 + // will mean that we don't block on the message pump until there was nothing 1.186 + // more to do. We also set this to true to make sure not to block on the 1.187 + // first iteration of the loop, so RunAllPending() works correctly. 1.188 + bool more_work_is_plausible = true; 1.189 + 1.190 + // We run our own loop instead of using g_main_loop_quit in one of the 1.191 + // callbacks. This is so we only quit our own loops, and we don't quit 1.192 + // nested loops run by others. TODO(deanm): Is this what we want? 1.193 + for (;;) { 1.194 + // Don't block if we think we have more work to do. 1.195 + bool block = !more_work_is_plausible; 1.196 + 1.197 + // g_main_context_iteration returns true if events have been dispatched. 1.198 + more_work_is_plausible = g_main_context_iteration(context_, block); 1.199 + if (state_->should_quit) 1.200 + break; 1.201 + 1.202 + more_work_is_plausible |= state_->delegate->DoWork(); 1.203 + if (state_->should_quit) 1.204 + break; 1.205 + 1.206 + more_work_is_plausible |= 1.207 + state_->delegate->DoDelayedWork(&delayed_work_time_); 1.208 + if (state_->should_quit) 1.209 + break; 1.210 + 1.211 + if (more_work_is_plausible) 1.212 + continue; 1.213 + 1.214 + more_work_is_plausible = state_->delegate->DoIdleWork(); 1.215 + if (state_->should_quit) 1.216 + break; 1.217 + } 1.218 + 1.219 + state_ = previous_state; 1.220 +} 1.221 + 1.222 +// Return the timeout we want passed to poll. 1.223 +int MessagePumpForUI::HandlePrepare() { 1.224 + // We know we have work, but we haven't called HandleDispatch yet. Don't let 1.225 + // the pump block so that we can do some processing. 1.226 + if (state_ && // state_ may be null during tests. 1.227 + state_->has_work) 1.228 + return 0; 1.229 + 1.230 + // We don't think we have work to do, but make sure not to block 1.231 + // longer than the next time we need to run delayed work. 1.232 + return GetTimeIntervalMilliseconds(delayed_work_time_); 1.233 +} 1.234 + 1.235 +bool MessagePumpForUI::HandleCheck() { 1.236 + if (!state_) // state_ may be null during tests. 1.237 + return false; 1.238 + 1.239 + // We should only ever have a single message on the wakeup pipe, since we 1.240 + // are only signaled when the queue went from empty to non-empty. The glib 1.241 + // poll will tell us whether there was data, so this read shouldn't block. 1.242 + if (wakeup_gpollfd_->revents & G_IO_IN) { 1.243 + char msg; 1.244 + if (HANDLE_EINTR(read(wakeup_pipe_read_, &msg, 1)) != 1 || msg != '!') { 1.245 + NOTREACHED() << "Error reading from the wakeup pipe."; 1.246 + } 1.247 + // Since we ate the message, we need to record that we have more work, 1.248 + // because HandleCheck() may be called without HandleDispatch being called 1.249 + // afterwards. 1.250 + state_->has_work = true; 1.251 + } 1.252 + 1.253 + if (state_->has_work) 1.254 + return true; 1.255 + 1.256 + if (GetTimeIntervalMilliseconds(delayed_work_time_) == 0) { 1.257 + // The timer has expired. That condition will stay true until we process 1.258 + // that delayed work, so we don't need to record this differently. 1.259 + return true; 1.260 + } 1.261 + 1.262 + return false; 1.263 +} 1.264 + 1.265 +void MessagePumpForUI::HandleDispatch() { 1.266 + state_->has_work = false; 1.267 + if (state_->delegate->DoWork()) { 1.268 + // NOTE: on Windows at this point we would call ScheduleWork (see 1.269 + // MessagePumpForUI::HandleWorkMessage in message_pump_win.cc). But here, 1.270 + // instead of posting a message on the wakeup pipe, we can avoid the 1.271 + // syscalls and just signal that we have more work. 1.272 + state_->has_work = true; 1.273 + } 1.274 + 1.275 + if (state_->should_quit) 1.276 + return; 1.277 + 1.278 + state_->delegate->DoDelayedWork(&delayed_work_time_); 1.279 +} 1.280 + 1.281 +void MessagePumpForUI::AddObserver(Observer* observer) { 1.282 + observers_.AddObserver(observer); 1.283 +} 1.284 + 1.285 +void MessagePumpForUI::RemoveObserver(Observer* observer) { 1.286 + observers_.RemoveObserver(observer); 1.287 +} 1.288 + 1.289 +void MessagePumpForUI::WillProcessEvent(GdkEvent* event) { 1.290 + FOR_EACH_OBSERVER(Observer, observers_, WillProcessEvent(event)); 1.291 +} 1.292 + 1.293 +void MessagePumpForUI::DidProcessEvent(GdkEvent* event) { 1.294 + FOR_EACH_OBSERVER(Observer, observers_, DidProcessEvent(event)); 1.295 +} 1.296 + 1.297 +void MessagePumpForUI::Quit() { 1.298 + if (state_) { 1.299 + state_->should_quit = true; 1.300 + } else { 1.301 + NOTREACHED() << "Quit called outside Run!"; 1.302 + } 1.303 +} 1.304 + 1.305 +void MessagePumpForUI::ScheduleWork() { 1.306 + // This can be called on any thread, so we don't want to touch any state 1.307 + // variables as we would then need locks all over. This ensures that if 1.308 + // we are sleeping in a poll that we will wake up. 1.309 + char msg = '!'; 1.310 + if (HANDLE_EINTR(write(wakeup_pipe_write_, &msg, 1)) != 1) { 1.311 + NOTREACHED() << "Could not write to the UI message loop wakeup pipe!"; 1.312 + } 1.313 +} 1.314 + 1.315 +void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 1.316 + // We need to wake up the loop in case the poll timeout needs to be 1.317 + // adjusted. This will cause us to try to do work, but that's ok. 1.318 + delayed_work_time_ = delayed_work_time; 1.319 + ScheduleWork(); 1.320 +} 1.321 + 1.322 +// static 1.323 +void MessagePumpForUI::EventDispatcher(GdkEvent* event, gpointer data) { 1.324 + MessagePumpForUI* message_pump = reinterpret_cast<MessagePumpForUI*>(data); 1.325 + 1.326 + message_pump->WillProcessEvent(event); 1.327 + if (message_pump->state_ && // state_ may be null during tests. 1.328 + message_pump->state_->dispatcher) { 1.329 + if (!message_pump->state_->dispatcher->Dispatch(event)) 1.330 + message_pump->state_->should_quit = true; 1.331 + } else { 1.332 + gtk_main_do_event(event); 1.333 + } 1.334 + message_pump->DidProcessEvent(event); 1.335 +} 1.336 + 1.337 +} // namespace base