blob: 4b53f4e2c2401251ed5032d3af20cd638309ec2d [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
darin@google.coma2ac02b2008-08-15 13:32:57 +09004
5#ifndef BASE_MESSAGE_PUMP_H_
6#define BASE_MESSAGE_PUMP_H_
7
8#include "base/ref_counted.h"
9
darin@google.com6393bed2008-08-20 15:30:58 +090010class Time;
darin@google.coma2ac02b2008-08-15 13:32:57 +090011
12namespace base {
13
14class MessagePump : public RefCountedThreadSafe<MessagePump> {
15 public:
16 // Please see the comments above the Run method for an illustration of how
17 // these delegate methods are used.
18 class Delegate {
19 public:
darin@google.com12d40bb2008-08-20 03:36:23 +090020 virtual ~Delegate() {}
21
darin@google.coma2ac02b2008-08-15 13:32:57 +090022 // Called from within Run in response to ScheduleWork or when the message
23 // pump would otherwise call DoDelayedWork. Returns true to indicate that
24 // work was done. DoDelayedWork will not be called if DoWork returns true.
25 virtual bool DoWork() = 0;
26
27 // Called from within Run in response to ScheduleDelayedWork or when the
28 // message pump would otherwise sleep waiting for more work. Returns true
29 // to indicate that delayed work was done. DoIdleWork will not be called
darin@google.com6393bed2008-08-20 15:30:58 +090030 // if DoDelayedWork returns true. Upon return |next_delayed_work_time|
31 // indicates the time when DoDelayedWork should be called again. If
32 // |next_delayed_work_time| is null (per Time::is_null), then the queue of
33 // future delayed work (timer events) is currently empty, and no additional
34 // calls to this function need to be scheduled.
35 virtual bool DoDelayedWork(Time* next_delayed_work_time) = 0;
darin@google.coma2ac02b2008-08-15 13:32:57 +090036
37 // Called from within Run just before the message pump goes to sleep.
38 // Returns true to indicate that idle work was done.
39 virtual bool DoIdleWork() = 0;
40 };
41
42 virtual ~MessagePump() {}
43
44 // The Run method is called to enter the message pump's run loop.
45 //
46 // Within the method, the message pump is responsible for processing native
47 // messages as well as for giving cycles to the delegate periodically. The
48 // message pump should take care to mix delegate callbacks with native
49 // message processing so neither type of event starves the other of cycles.
50 //
51 // The anatomy of a typical run loop:
52 //
53 // for (;;) {
54 // bool did_work = DoInternalWork();
55 // if (should_quit_)
56 // break;
57 // did_work |= delegate_->DoWork();
58 // if (should_quit_)
59 // break;
60 // if (did_work)
61 // continue;
62 //
63 // did_work = delegate_->DoDelayedWork();
64 // if (should_quit_)
65 // break;
66 // if (did_work)
67 // continue;
68 //
69 // did_work = delegate_->DoIdleWork();
70 // if (should_quit_)
71 // break;
72 // if (did_work)
73 // continue;
74 //
75 // WaitForWork();
76 // }
77 //
78 // Here, DoInternalWork is some private method of the message pump that is
79 // responsible for dispatching the next UI message or notifying the next IO
80 // completion (for example). WaitForWork is a private method that simply
81 // blocks until there is more work of any type to do.
82 //
83 // Notice that the run loop alternates between calling DoInternalWork and
84 // calling the delegate's DoWork method. This helps ensure that neither work
85 // queue starves the other. However, DoDelayedWork may be starved. The
86 // implementation may decide to periodically let some DoDelayedWork calls go
87 // through if either DoInternalWork or DoWork is dominating the run loop.
88 // This can be important for message pumps that are used to drive animations,
89 // for example.
90 //
91 // Notice also that after each callout to foreign code, the run loop checks
92 // to see if it should quit. The Quit method is responsible for setting this
93 // flag. No further work is done once the quit flag is set.
94 //
95 // NOTE: Care must be taken to handle Run being called again from within any
96 // of the callouts to foreign code. Native message pumps may also need to
97 // deal with other native message pumps being run outside their control
98 // (e.g., the MessageBox API on Windows pumps UI messages!). To be specific,
99 // the callouts (DoWork and DoDelayedWork) MUST still be provided even in
100 // nested sub-loops that are "seemingly" outside the control of this message
101 // pump. DoWork in particular must never be starved for time slices unless
102 // it returns false (meaning it has run out of things to do).
103 //
104 virtual void Run(Delegate* delegate) = 0;
105
106 // Quit immediately from the most recently entered run loop. This method may
107 // only be used on the thread that called Run.
108 virtual void Quit() = 0;
109
110 // Schedule a DoWork callback to happen reasonably soon. Does nothing if a
111 // DoWork callback is already scheduled. This method may be called from any
112 // thread. Once this call is made, DoWork should not be "starved" at least
113 // until it returns a value of false.
114 virtual void ScheduleWork() = 0;
115
darin@google.com6393bed2008-08-20 15:30:58 +0900116 // Schedule a DoDelayedWork callback to happen at the specified time,
darin@google.coma2ac02b2008-08-15 13:32:57 +0900117 // cancelling any pending DoDelayedWork callback. This method may only be
118 // used on the thread that called Run.
darin@google.com6393bed2008-08-20 15:30:58 +0900119 virtual void ScheduleDelayedWork(const Time& delayed_work_time) = 0;
darin@google.coma2ac02b2008-08-15 13:32:57 +0900120};
121
122} // namespace base
123
124#endif // BASE_MESSAGE_PUMP_H_
license.botf003cfe2008-08-24 09:55:55 +0900125