| Index: base/message_pump_glib.cc
|
| ===================================================================
|
| --- base/message_pump_glib.cc (revision 14449)
|
| +++ base/message_pump_glib.cc (working copy)
|
| @@ -4,12 +4,14 @@
|
|
|
| #include "base/message_pump_glib.h"
|
|
|
| +#include <errno.h>
|
| #include <fcntl.h>
|
| #include <math.h>
|
|
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| #include "base/platform_thread.h"
|
| +#include "base/scoped_ptr.h"
|
|
|
| namespace {
|
|
|
| @@ -90,6 +92,9 @@
|
|
|
| namespace base {
|
|
|
| +// static
|
| +Lock MessagePumpForUI::glib_main_loop_lock_;
|
| +
|
| MessagePumpForUI::MessagePumpForUI()
|
| : state_(NULL),
|
| context_(g_main_context_default()) {
|
| @@ -118,6 +123,45 @@
|
| close(wakeup_pipe_write_);
|
| }
|
|
|
| +// Runs a glib main loop iteration. Grabs glib_main_loop_lock_ while
|
| +// calling glib functions, but releases it while polling.
|
| +static void GMainIterate(GMainContext* context) {
|
| + AutoLock locked(MessagePumpForUI::glib_main_loop_lock_);
|
| + int fds_array_size = 50;
|
| + scoped_array<GPollFD> fds(new GPollFD[fds_array_size]);
|
| +
|
| + // We use the lower-level component functions and do the poll
|
| + // ourselves so that we can release glib_main_loop_lock_ while
|
| + // polling, otherwise waiters might starve.
|
| +
|
| + // I'll assume no other thread will g_main_context_acquire the
|
| + // context away from this thread. We cannot g_main_context_wait as
|
| + // we can't get to the condition and mutex in the context (which is
|
| + // externally opaque).
|
| +
|
| + gint max_priority, timeout;
|
| + g_main_context_prepare(context, &max_priority);
|
| + int number_of_fds = g_main_context_query(context, max_priority, &timeout,
|
| + fds.get(), fds_array_size);
|
| + // We could reallocate instead, then we'd want to cache the array size...
|
| + CHECK(number_of_fds <= fds_array_size);
|
| + GPollFunc poll_func = g_main_context_get_poll_func(context);
|
| +
|
| + {
|
| + // Release the lock while polling
|
| + AutoUnlock locked(MessagePumpForUI::glib_main_loop_lock_);
|
| +
|
| + if ((*poll_func) (fds.get(), number_of_fds, timeout) < 0) {
|
| + if (errno != EINTR)
|
| + LOG(ERROR) << "g_main_loop poll error: " << strerror(errno);
|
| + // Just carry on.
|
| + }
|
| + }
|
| +
|
| + g_main_context_check(context, max_priority, fds.get(), number_of_fds);
|
| + g_main_context_dispatch(context);
|
| +}
|
| +
|
| void MessagePumpForUI::Run(Delegate* delegate) {
|
| #ifndef NDEBUG
|
| // Make sure we only run this on one thread. GTK only has one message pump
|
| @@ -146,7 +190,7 @@
|
| // callbacks. This is so we only quit our own loops, and we don't quit
|
| // nested loops run by others. TODO(deanm): Is this what we want?
|
| while (!state_->should_quit)
|
| - g_main_context_iteration(context_, true);
|
| + GMainIterate(context_);
|
|
|
| state_ = previous_state;
|
| }
|
|
|