summaryrefslogtreecommitdiffstats
path: root/base/message_loop.h
diff options
context:
space:
mode:
authordarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-15 04:32:57 +0000
committerdarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-15 04:32:57 +0000
commit295039bdf97f08bf5c1c1c136dd977b7e97ddd31 (patch)
treeae3b47308e7d2f2db903f6a61c193e7a8c9ec882 /base/message_loop.h
parent1c33790ef99bf8301260b9144110e71e7723d0f4 (diff)
downloadchromium_src-295039bdf97f08bf5c1c1c136dd977b7e97ddd31.zip
chromium_src-295039bdf97f08bf5c1c1c136dd977b7e97ddd31.tar.gz
chromium_src-295039bdf97f08bf5c1c1c136dd977b7e97ddd31.tar.bz2
Introduce MessagePump to represent the native message pump used to drive a
MessageLoop. A MessageLoop now has a MessagePump. This will make it possible to port the MessagePump interface to other platforms as well as to use an IO completion port for our worker threads on Windows. Currently, there is only MessagePumpWin, which attempts to preserve the pre-existing behavior of the MessageLoop. API changes to MessageLoop: 1. MessageLoop::Quit means return from Run when the MessageLoop would otherwise wait for more work. 2. MessageLoop::Quit can no longer be called outside the context of an active Run call. So, things like this: MessageLoop::current()->Quit(); MessageLoop::current()->Run(); are now: MessageLoop::current()->RunAllPending(); 3. MessageLoop::Quit can no longer be called from other threads. This means that PostTask(..., new MessageLoop::QuitTask()) must be used explicitly to Quit across thread boundaries. 4. No protection is made to deal with nested MessageLoops involving watched objects or APCs. In fact, an assertion is added to flag such cases. This is a temporary measure until object watching and APC facilities are removed in favor of a MessagePump designed around an IO completion port. As part of this CL, I also changed the automation system to use an IPC::ChannelProxy instead of an IPC::Channel. This moves the automation IPC onto Chrome's IO thread where it belongs. I also fixed some abuses of RefCounted in the AutomationProvider class. It was deleting itself in some cases! This led to having to fix the ownership model for AutomationProvider, which explains the changes to AutomationProviderList and so on. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@928 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/message_loop.h')
-rw-r--r--base/message_loop.h413
1 files changed, 118 insertions, 295 deletions
diff --git a/base/message_loop.h b/base/message_loop.h
index 81c1e52..8ae12c8 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -27,8 +27,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef BASE_MESSAGE_LOOP_H__
-#define BASE_MESSAGE_LOOP_H__
+#ifndef BASE_MESSAGE_LOOP_H_
+#define BASE_MESSAGE_LOOP_H_
#include <deque>
#include <queue>
@@ -36,33 +36,39 @@
#include <vector>
#include "base/histogram.h"
+#include "base/message_pump.h"
#include "base/observer_list.h"
-#include "base/id_map.h"
+#include "base/ref_counted.h"
#include "base/task.h"
#include "base/timer.h"
#include "base/thread_local_storage.h"
-//
-// A MessageLoop is used to process events for a particular thread.
-// There is at most one MessageLoop instance per thread.
-// Events include Windows Message Queue messages, Tasks submitted to PostTask
-// or managed by TimerManager, APC calls (as time permits), and signals sent to
-// a registered set of HANDLES.
-// Processing events corresponds (respectively) to dispatching Windows messages,
-// running Tasks, yielding time to APCs, and calling Watchers when the
-// corresponding HANDLE is signaled.
+#if defined(OS_WIN)
+// We need this to declare base::MessagePumpWin::Dispatcher, which we should
+// really just eliminate.
+#include "base/message_pump_win.h"
+#endif
+// A MessageLoop is used to process events for a particular thread. There is
+// at most one MessageLoop instance per thread.
+//
+// Events include at minimum Task instances submitted to PostTask or those
+// managed by TimerManager. Depending on the type of message pump used by the
+// MessageLoop other events such as UI messages may be processed. On Windows
+// APC calls (as time permits) and signals sent to a registered set of HANDLEs
+// may also be processed.
//
// NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
// on the thread where the MessageLoop's Run method executes.
//
-// WARNING: MessageLoop has task reentrancy protection. This means that if a
+// NOTE: MessageLoop has task reentrancy protection. This means that if a
// task is being processed, a second task cannot start until the first task is
-// finished. Reentrancy can happen when processing a task, and an inner message
-// pump is created. That inner pump then processes windows messages which could
-// implicitly start an inner task. Inner messages pumps are created with dialogs
-// (DialogBox), common dialogs (GetOpenFileName), OLE functions (DoDragDrop),
-// printer functions (StartDoc) and *many* others.
+// finished. Reentrancy can happen when processing a task, and an inner
+// message pump is created. That inner pump then processes native messages
+// which could implicitly start an inner task. Inner message pumps are created
+// with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
+// (DoDragDrop), printer functions (StartDoc) and *many* others.
+//
// Sample workaround when inner task processing is needed:
// bool old_state = MessageLoop::current()->NestableTasksAllowed();
// MessageLoop::current()->SetNestableTasksAllowed(true);
@@ -70,142 +76,13 @@
// MessageLoop::current()->SetNestableTasksAllowed(old_state);
// // Process hr (the result returned by DoDragDrop().
//
-// Please be **SURE** your task is reentrant and all global variables are stable
-// and accessible before calling SetNestableTasksAllowed(true).
-//
-
-// Message loop has several distinct functions. It provides message pumps,
-// responds to windows message dispatches, manipulates queues of Tasks.
-// The most central operation is the implementation of message pumps, along with
-// several subtleties.
-
-// MessageLoop currently implements several different message pumps. A message
-// pump is (traditionally) something that reads from an incoming queue, and then
-// dispatches the work.
-//
-// The first message pump, RunTraditional(), is among other things a
-// traditional Windows Message pump. It contains a nearly infinite loop that
-// peeks out messages, and then dispatches them.
-// Intermixed with those peeks are checks on a queue of Tasks, checks for
-// signaled objects, and checks to see if TimerManager has tasks to run.
-// When there are no events to be serviced, this pump goes into a wait state.
-// For 99.99% of all events, this first message pump handles all processing.
-//
-// When a task, or windows event, invokes on the stack a native dialog box or
-// such, that window typically provides a bare bones (native?) message pump.
-// That bare-bones message pump generally supports little more than a peek of
-// the Windows message queue, followed by a dispatch of the peeked message.
-// MessageLoop extends that bare-bones message pump to also service Tasks, at
-// the cost of some complexity.
-// The basic structure of the extension (refered to as a sub-pump) is that a
-// special message,kMsgPumpATask, is repeatedly injected into the Windows
-// Message queue. Each time the kMsgPumpATask message is peeked, checks are made
-// for an extended set of events, including the availability of Tasks to run.
-//
-// After running a task, the special message kMsgPumpATask is again posted to
-// the Windows Message queue, ensuring a future time slice for processing a
-// future event.
-//
-// To prevent flooding the Windows Message queue, care is taken to be sure that
-// at most one kMsgPumpATask message is EVER pending in the Winow's Message
-// queue.
+// Please be SURE your task is reentrant (nestable) and all global variables
+// are stable and accessible before calling SetNestableTasksAllowed(true).
//
-// There are a few additional complexities in this system where, when there are
-// no Tasks to run, this otherwise infinite stream of messages which drives the
-// sub-pump is halted. The pump is automatically re-started when Tasks are
-// queued.
-//
-// A second complexity is that the presence of this stream of posted tasks may
-// prevent a bare-bones message pump from ever peeking a WM_PAINT or WM_TIMER.
-// Such paint and timer events always give priority to a posted message, such as
-// kMsgPumpATask messages. As a result, care is taken to do some peeking in
-// between the posting of each kMsgPumpATask message (i.e., after kMsgPumpATask
-// is peeked, and before a replacement kMsgPumpATask is posted).
-//
-//
-// NOTE: Although it may seem odd that messages are used to start and stop this
-// flow (as opposed to signaling objects, etc.), it should be understood that
-// the native message pump will *only* respond to messages. As a result, it is
-// an excellent choice. It is also helpful that the starter messages that are
-// placed in the queue when new task arrive also awakens the RunTraditional()
-// loop.
-
-//------------------------------------------------------------------------------
-class MessageLoop {
+class MessageLoop : public base::MessagePump::Delegate {
public:
-
- // Select a non-default strategy for serving pending requests, that is to be
- // used by all MessageLoop instances. This is called only once before
- // constructing any instances.
- static void SetStrategy(int strategy);
static void EnableHistogrammer(bool enable_histogrammer);
-#ifdef OS_WIN
- // Used with WatchObject to asynchronously monitor the signaled state of a
- // HANDLE object.
- class Watcher {
- public:
- virtual ~Watcher() {}
- // Called from MessageLoop::Run when a signalled object is detected.
- virtual void OnObjectSignaled(HANDLE object) = 0;
- };
-
- // Have the current thread's message loop watch for a signaled object.
- // Pass a null watcher to stop watching the object.
- bool WatchObject(HANDLE, Watcher*);
-
- // An Observer is an object that receives global notifications from the
- // MessageLoop.
- //
- // NOTE: An Observer implementation should be extremely fast!
- //
- class Observer {
- public:
- virtual ~Observer() {}
-
- // This method is called before processing a message.
- // The message may be undefined in which case msg.message is 0
- virtual void WillProcessMessage(const MSG& msg) = 0;
-
- // This method is called when control returns from processing a UI message.
- // The message may be undefined in which case msg.message is 0
- virtual void DidProcessMessage(const MSG& msg) = 0;
- };
-
- // Add an Observer, which will start receiving notifications immediately.
- void AddObserver(Observer* observer);
-
- // Remove an Observer. It is safe to call this method while an Observer is
- // receiving a notification callback.
- void RemoveObserver(Observer* observer);
-
- // Give a chance to code processing additional messages to notify the
- // message loop observers that another message has been processed.
- void WillProcessMessage(const MSG& msg);
- void DidProcessMessage(const MSG& msg);
-
- // Dispatcher is used during a nested invocation of Run to dispatch events.
- // If Run is invoked with a non-NULL Dispatcher, MessageLoop does not
- // dispatch events (or invoke TranslateMessage), rather every message is
- // passed to Dispatcher's Dispatch method for dispatch. It is up to the
- // Dispatcher to dispatch, or not, the event.
- //
- // The nested loop is exited by either posting a quit, or returning false
- // from Dispatch.
- class Dispatcher {
- public:
- virtual ~Dispatcher() {}
- // Dispatches the event. If true is returned processing continues as
- // normal. If false is returned, the nested loop exits immediately.
- virtual bool Dispatch(const MSG& msg) = 0;
- };
-#else // !OS_WIN
- // On non-Windows platforms, the Dispatcher does not exist, but we allow the
- // typename to exist for convenience. On non-Windows platforms, a Dispatcher
- // pointer should always be NULL.
- class Dispatcher;
-#endif // OS_*
-
// A DestructionObserver is notified when the current MessageLoop is being
// destroyed. These obsevers are notified prior to MessageLoop::current()
// being changed to return NULL. This gives interested parties the chance to
@@ -283,19 +160,18 @@ class MessageLoop {
// Return as soon as all items that can be run are taken care of.
void RunAllPending();
- // See description of Dispatcher for how Run uses Dispatcher.
- void Run(Dispatcher* dispatcher);
-
// Signals the Run method to return after it is done processing all pending
- // messages. This method may be called from any thread, but no effort is
- // made to support concurrent calls to this method from multiple threads.
+ // messages. This method may only be called on the same thread that called
+ // Run, and Run must still be on the call stack.
+ //
+ // Use QuitTask if you need to Quit another thread's MessageLoop, but note
+ // that doing so is fairly dangerous if the target thread makes nested calls
+ // to MessageLoop::Run. The problem being that you won't know which nested
+ // run loop you are quiting, so be careful!
//
- // For example, the first call to Quit may lead to the MessageLoop being
- // deleted once its Run method returns, so a second call from another thread
- // could be problematic.
void Quit();
- // Invokes Quit on the current MessageLoop when run. Useful to schedule an
+ // Invokes Quit on the current MessageLoop when run. Useful to schedule an
// arbitrary MessageLoop to Quit.
class QuitTask : public Task {
public:
@@ -310,7 +186,10 @@ class MessageLoop {
~MessageLoop();
// Optional call to connect the thread name with this loop.
- void SetThreadName(const std::string& thread_name);
+ void set_thread_name(const std::string& thread_name) {
+ DCHECK(thread_name_.empty()) << "Should not rename this thread!";
+ thread_name_ = thread_name;
+ }
const std::string& thread_name() const { return thread_name_; }
// Returns the MessageLoop object for the current thread, or null if none.
@@ -347,51 +226,62 @@ class MessageLoop {
exception_restoration_ = restore;
}
- // Public entry point for TimerManager to request the Run() of a task. If we
- // created the task during an PostTask(FROM_HERE, ), then we will also perform
- // destructions, and we'll have the option of queueing the task. If we didn't
- // create the timer, then we will Run it immediately.
- bool RunTimerTask(Timer* timer);
+ //----------------------------------------------------------------------------
+#if defined(OS_WIN)
+ // Backwards-compat for the old Windows-specific MessageLoop API. These APIs
+ // are deprecated.
- // Since some Timer's are owned by MessageLoop, the TimerManager (when it is
- // being destructed) passses us the timers to discard (without doing a Run()).
- void DiscardTimer(Timer* timer);
+ typedef base::MessagePumpWin::Dispatcher Dispatcher;
+ typedef base::MessagePumpWin::Observer Observer;
+ typedef base::MessagePumpWin::Watcher Watcher;
- // Applications can call this to encourage us to process all pending WM_PAINT
- // messages.
- // This method will process all paint messages the Windows Message queue can
- // provide, up to some fixed number (to avoid any infinite loops).
- void PumpOutPendingPaintMessages();
+ void Run(Dispatcher* dispatcher);
+
+ void WatchObject(HANDLE object, Watcher* watcher) {
+ pump_win()->WatchObject(object, watcher);
+ }
+ void AddObserver(Observer* observer) {
+ pump_win()->AddObserver(observer);
+ }
+ void RemoveObserver(Observer* observer) {
+ pump_win()->RemoveObserver(observer);
+ }
+ void WillProcessMessage(const MSG& message) {
+ pump_win()->WillProcessMessage(message);
+ }
+ void DidProcessMessage(const MSG& message) {
+ pump_win()->DidProcessMessage(message);
+ }
+ void PumpOutPendingPaintMessages() {
+ pump_win()->PumpOutPendingPaintMessages();
+ }
+#endif // defined(OS_WIN)
//----------------------------------------------------------------------------
private:
friend class TimerManager; // So it can call DidChangeNextTimerExpiry
- struct ScopedStateSave {
- explicit ScopedStateSave(MessageLoop* loop)
- : loop_(loop),
- dispatcher_(loop->dispatcher_),
- quit_now_(loop->quit_now_),
- quit_received_(loop->quit_received_),
- run_depth_(loop->run_depth_) {
- loop->quit_now_ = loop->quit_received_ = false;
- ++loop->run_depth_;
- }
+ struct RunState {
+ // Used to count how many Run() invocations are on the stack.
+ int run_depth;
- ~ScopedStateSave() {
- loop_->run_depth_ = run_depth_;
- loop_->quit_received_ = quit_received_;
- loop_->quit_now_ = quit_now_;
- loop_->dispatcher_ = dispatcher_;
- }
+ // Used to record that Quit() was called, or that we should quit the pump
+ // once it becomes idle.
+ bool quit_received;
+
+#if defined(OS_WIN)
+ base::MessagePumpWin::Dispatcher* dispatcher;
+#endif
+ };
+ class AutoRunState : RunState {
+ public:
+ AutoRunState(MessageLoop* loop);
+ ~AutoRunState();
private:
MessageLoop* loop_;
- Dispatcher* dispatcher_;
- bool quit_now_;
- bool quit_received_;
- int run_depth_;
- }; // struct ScopedStateSave
+ RunState* previous_state_;
+ };
// A prioritized queue with interface that mostly matches std::queue<>.
// For debugging/performance testing, you can swap in std::queue<Task*>.
@@ -458,32 +348,22 @@ class MessageLoop {
DISALLOW_EVIL_CONSTRUCTORS(OptionallyPrioritizedTaskQueue);
};
-#ifdef OS_WIN
- void InitMessageWnd();
-
- // Windows procedure for message_hwnd_.
- static LRESULT CALLBACK WndProcThunk(
- HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
- LRESULT WndProc(
- HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-#endif // OS_WIN
+#if defined(OS_WIN)
+ base::MessagePumpWin* pump_win() {
+ return static_cast<base::MessagePumpWin*>(pump_.get());
+ }
+#endif
// A function to encapsulate all the exception handling capability in the
- // stacks around the running of a main message loop.
- // It will run the message loop in a SEH try block or not depending on the
- // set_SEH_restoration() flag.
- void RunHandler(Dispatcher* dispatcher, bool non_blocking);
+ // stacks around the running of a main message loop. It will run the message
+ // loop in a SEH try block or not depending on the set_SEH_restoration()
+ // flag.
+ void RunHandler();
// A surrounding stack frame around the running of the message loop that
// supports all saving and restoring of state, as is needed for any/all (ugly)
// recursive calls.
- void RunInternal(Dispatcher* dispatcher, bool non_blocking);
-
- // An extended message loop (message pump) that loops mostly forever, and
- // processes task, signals, timers, etc.
- // If non-blocking is set, it will return rather than wait for new things to
- // arrive for processing.
- void RunTraditional(bool non_blocking);
+ void RunInternal();
//----------------------------------------------------------------------------
// A list of method wrappers with identical calling signatures (no arguments)
@@ -492,52 +372,18 @@ class MessageLoop {
bool ProcessNextDeferredTask();
bool ProcessNextDelayedNonNestableTask();
- bool ProcessNextObject();
bool ProcessSomeTimers();
//----------------------------------------------------------------------------
- // Process some pending messages. Returns true if a message was processed.
- bool ProcessNextWindowsMessage();
-
- // Wait until either an object is signaled, a message is available, a timer
- // needs attention, or our incoming_queue_ has gotten a task.
- // Handle (without returning) any APCs (only IO thread currently has APCs.)
- void WaitForWork();
-
-#ifdef OS_WIN
- // Helper function for processing window messages. This includes handling
- // WM_QUIT, message translation and dispatch, etc.
- //
- // If dispatcher_ is non-NULL this method does NOT dispatch the event, instead
- // it invokes Dispatch on the dispatcher_.
- bool ProcessMessageHelper(const MSG& msg);
-#endif // OS_WIN
-
- // When we encounter a kMsgPumpATask, the following helper can be called to
- // peek and process a replacement message, such as a WM_PAINT or WM_TIMER.
- // The goal is to make the kMsgPumpATask as non-intrusive as possible, even
- // though a continuous stream of such messages are posted. This method
- // carefully peeks a message while there is no chance for a kMsgPumpATask to
- // be pending, then releases the lock (allowing a replacement kMsgPumpATask to
- // possibly be posted), and finally dispatches that peeked replacement.
- // Note that the re-post of kMsgPumpATask may be asynchronous to this thread!!
- bool ProcessPumpReplacementMessage();
-
- // Signals a watcher if a wait falls within the range of objects we're
- // waiting on. object_index is the offset in objects_ that was signaled.
- // Returns true if an object was signaled.
- bool SignalWatcher(size_t object_index);
-
// Run a work_queue_ task or new_task, and delete it (if it was processed by
// PostTask). If there are queued tasks, the oldest one is executed and
// new_task is queued. new_task is optional and can be NULL. In this NULL
// case, the method will run one pending task (if any exist). Returns true if
- // it executes a task.
- // Queued tasks accumulate only when there is a nonreentrant task currently
- // processing, in which case the new_task is appended to the list
- // work_queue_. Such re-entrancy generally happens when an unrequested
- // message pump (typical of a native dialog) is executing in the context of a
- // task.
+ // it executes a task. Queued tasks accumulate only when there is a
+ // non-nestable task currently processing, in which case the new_task is
+ // appended to the list work_queue_. Such re-entrancy generally happens when
+ // an unrequested message pump (typical of a native dialog) is executing in
+ // the context of a task.
bool QueueOrRunTask(Task* new_task);
// Runs the specified task and deletes it.
@@ -548,14 +394,6 @@ class MessageLoop {
void BeforeTaskRunSetup();
void AfterTaskRunRestore();
- // When processing messages in our MessageWndProc(), we are sometimes called
- // by a native message pump (i.e., We are not called out of our Run() pump).
- // In those cases, we need to process tasks during the Windows Message
- // callback. This method processes a task, and also posts a new kMsgPumpATask
- // messages to the Windows Msg Queue so that we are called back later (to
- // process additional tasks).
- void PumpATaskDuringWndProc();
-
// Load tasks from the incoming_queue_ into work_queue_ if the latter is
// empty. The former requires a lock to access, while the latter is directly
// accessible on this thread.
@@ -565,19 +403,27 @@ class MessageLoop {
// destructor to make sure all the task's destructors get called.
void DeletePendingTasks();
- // Make sure a kPumpATask message is in flight, which starts/continues the
- // sub-pump.
- void EnsurePumpATaskWasPosted();
-
- // Do a PostMessage(), and crash if we can't eventually do the post.
- void EnsureMessageGetsPosted(int message) const;
-
// Post a task to our incomming queue.
void PostTaskInternal(Task* task);
// Called by the TimerManager when its next timer changes.
void DidChangeNextTimerExpiry();
+ // Entry point for TimerManager to request the Run() of a task. If we
+ // created the task during an PostTask(FROM_HERE, ), then we will also
+ // perform destructions, and we'll have the option of queueing the task. If
+ // we didn't create the timer, then we will Run it immediately.
+ bool RunTimerTask(Timer* timer);
+
+ // Since some Timer's are owned by MessageLoop, the TimerManager (when it is
+ // being destructed) passses us the timers to discard (without doing a Run()).
+ void DiscardTimer(Timer* timer);
+
+ // base::MessagePump::Delegate methods:
+ virtual bool DoWork();
+ virtual bool DoDelayedWork();
+ virtual bool DoIdleWork();
+
// Start recording histogram info about events and action IF it was enabled
// and IF the statistics recorder can accept a registration of our histogram.
void StartHistogrammer();
@@ -588,7 +434,6 @@ class MessageLoop {
void HistogramEvent(int event);
static TLSSlot tls_index_;
- static int strategy_selector_;
static const LinearHistogram::DescriptionPair event_descriptions_[];
static bool enable_histogrammer_;
@@ -603,29 +448,15 @@ class MessageLoop {
// there was no real prioritization.
OptionallyPrioritizedTaskQueue work_queue_;
-#ifdef OS_WIN
- HWND message_hwnd_;
-
- // A vector of objects (and corresponding watchers) that are routinely
- // serviced by this message loop's pump.
- std::vector<HANDLE> objects_;
- std::vector<Watcher*> watchers_;
-
- ObserverList<Observer> observers_;
-#endif // OS_WIN
+ scoped_refptr<base::MessagePump> pump_;
ObserverList<DestructionObserver> destruction_observers_;
- IDMap<Task> timed_tasks_;
// A recursion block that prevents accidentally running additonal tasks when
// insider a (accidentally induced?) nested message pump.
bool nestable_tasks_allowed_;
bool exception_restoration_;
- Dispatcher* dispatcher_;
- bool quit_received_;
- bool quit_now_;
-
std::string thread_name_;
// A profiling histogram showing the counts of various messages and events.
scoped_ptr<LinearHistogram> message_histogram_;
@@ -643,17 +474,9 @@ class MessageLoop {
// will execute once we're out of nested message loops.
TaskQueue delayed_non_nestable_queue_;
- // Indicate if there is a kMsgPumpATask message pending in the Windows Message
- // queue. There is at most one such message, and it can drive execution of
- // tasks when a native message pump is running.
- bool task_pump_message_pending_;
- // Protect access to task_pump_message_pending_.
- Lock task_pump_message_lock_;
-
- // Used to count how many Run() invocations are on the stack.
- int run_depth_;
+ RunState* state_;
- DISALLOW_EVIL_CONSTRUCTORS(MessageLoop);
+ DISALLOW_COPY_AND_ASSIGN(MessageLoop);
};
-#endif // BASE_MESSAGE_LOOP_H__
+#endif // BASE_MESSAGE_LOOP_H_