Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: base/message_pump_mac.h

Issue 7276045: Give a CFRunLoop to the IO message loop type on Mac OS X. Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // The basis for all native run loops on the Mac is the CFRunLoop. It can be 5 // The basis for all native run loops on the Mac is the CFRunLoop. It can be
6 // used directly, it can be used as the driving force behind the similar 6 // used directly, it can be used as the driving force behind the similar
7 // Foundation NSRunLoop, and it can be used to implement higher-level event 7 // Foundation NSRunLoop, and it can be used to implement higher-level event
8 // loops such as the NSApplication event loop. 8 // loops such as the NSApplication event loop.
9 // 9 //
10 // This file introduces a basic CFRunLoop-based implementation of the 10 // This file introduces a basic CFRunLoop-based implementation of the
(...skipping 14 matching lines...) Expand all
25 // any other thread, one of the other concrete subclasses is preferrable. 25 // any other thread, one of the other concrete subclasses is preferrable.
26 // MessagePumpMac::Create is defined, which returns a new NSApplication-based 26 // MessagePumpMac::Create is defined, which returns a new NSApplication-based
27 // or NSRunLoop-based MessagePump subclass depending on which thread it is 27 // or NSRunLoop-based MessagePump subclass depending on which thread it is
28 // called on. 28 // called on.
29 29
30 #ifndef BASE_MESSAGE_PUMP_MAC_H_ 30 #ifndef BASE_MESSAGE_PUMP_MAC_H_
31 #define BASE_MESSAGE_PUMP_MAC_H_ 31 #define BASE_MESSAGE_PUMP_MAC_H_
32 #pragma once 32 #pragma once
33 33
34 #include "base/message_pump.h" 34 #include "base/message_pump.h"
35 #include "base/observer_list.h"
35 36
36 #include <CoreFoundation/CoreFoundation.h> 37 #include <CoreFoundation/CoreFoundation.h>
37 38
38 #if !defined(__OBJC__) 39 #if !defined(__OBJC__)
39 class NSAutoreleasePool; 40 class NSAutoreleasePool;
40 #else // !defined(__OBJC__) 41 #else // !defined(__OBJC__)
41 #import <AppKit/AppKit.h> 42 #import <AppKit/AppKit.h>
42 43
43 // Clients must subclass NSApplication and implement this protocol if they use 44 // Clients must subclass NSApplication and implement this protocol if they use
44 // MessagePumpMac. 45 // MessagePumpMac.
45 @protocol CrAppProtocol 46 @protocol CrAppProtocol
46 // Must return true if -[NSApplication sendEvent:] is currently on the stack. 47 // Must return true if -[NSApplication sendEvent:] is currently on the stack.
47 // See the comment for |CreateAutoreleasePool()| in the cc file for why this is 48 // See the comment for |CreateAutoreleasePool()| in the cc file for why this is
48 // necessary. 49 // necessary.
49 - (BOOL)isHandlingSendEvent; 50 - (BOOL)isHandlingSendEvent;
50 @end 51 @end
51 #endif // !defined(__OBJC__) 52 #endif // !defined(__OBJC__)
52 53
53 namespace base { 54 namespace base {
54 55
55 class TimeTicks; 56 class TimeTicks;
56 57
57 class MessagePumpCFRunLoopBase : public MessagePump { 58 class MessagePumpCFRunLoopBase : public MessagePump {
58 // Needs access to CreateAutoreleasePool. 59 // Needs access to CreateAutoreleasePool.
59 friend class MessagePumpScopedAutoreleasePool; 60 friend class MessagePumpScopedAutoreleasePool;
60 public: 61 public:
62 class IOObserver {
63 public:
64 IOObserver() {}
65
66 // An IOObserver is an object that receives IO notifications from the
67 // MessagePump.
68 //
69 // NOTE: An IOObserver implementation should be extremely fast!
70 virtual void WillProcessIOEvent() = 0;
71 virtual void DidProcessIOEvent() = 0;
72
73 protected:
74 virtual ~IOObserver() {}
75 };
76
77 // Used with WatchFileDescptor to asynchronously monitor the I/O readiness of
78 // a File Descriptor.
79 class Watcher {
80 public:
81 virtual ~Watcher() {}
82 // Called from MessageLoop::Run when an FD can be read from/written to
83 // without blocking
84 virtual void OnFileCanReadWithoutBlocking(int fd) = 0;
85 virtual void OnFileCanWriteWithoutBlocking(int fd) = 0;
86 };
87
88 // Object returned by WatchFileDescriptor to manage further watching.
89 class FileDescriptorWatcher {
90 public:
91 FileDescriptorWatcher();
92 ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor.
93
94 // NOTE: These methods aren't called StartWatching()/StopWatching() to
95 // avoid confusion with the win32 ObjectWatcher class.
96
97 // Stop watching the FD, always safe to call. No-op if there's nothing
98 // to do.
99 bool StopWatchingFileDescriptor();
100
101 private:
102 friend class MessagePumpCFRunLoopBase;
103
104 // Called by MessagePumpCFRunLoopBase, ownership of |fdref| and |fd_source|
105 // is transferred to this object.
106 void Init(CFFileDescriptorRef fdref,
107 CFOptionFlags callback_types,
108 CFRunLoopSourceRef fd_source,
109 bool is_persistent);
110
111 // Used by MessagePumpCFRunLoopBase to take ownership of fdref_.
112 CFFileDescriptorRef ReleaseCFFileDescriptor();
113
114 void set_pump(MessagePumpCFRunLoopBase* pump) { pump_ = pump; }
115 MessagePumpCFRunLoopBase* pump() { return pump_; }
116
117 void set_watcher(Watcher* watcher) { watcher_ = watcher; }
118
119 void OnFileCanReadWithoutBlocking(int fd, MessagePumpCFRunLoopBase* pump);
120 void OnFileCanWriteWithoutBlocking(int fd, MessagePumpCFRunLoopBase* pump);
121
122 bool is_persistent_; // false if this event is one-shot.
123 CFFileDescriptorRef fdref_;
124 CFOptionFlags callback_types_;
125 CFRunLoopSourceRef fd_source_;
126 MessagePumpCFRunLoopBase* pump_;
127 Watcher* watcher_;
128
129 DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher);
130 };
131
132 enum Mode {
133 WATCH_READ = 1 << 0,
134 WATCH_WRITE = 1 << 1,
135 WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE
136 };
137
61 MessagePumpCFRunLoopBase(); 138 MessagePumpCFRunLoopBase();
62 virtual ~MessagePumpCFRunLoopBase(); 139 virtual ~MessagePumpCFRunLoopBase();
63 140
141 // Have the current thread's message loop watch for a a situation in which
142 // reading/writing to the FD can be performed without blocking.
143 // Callers must provide a preallocated FileDescriptorWatcher object which
144 // can later be used to manage the lifetime of this event.
145 // If a FileDescriptorWatcher is passed in which is already attached to
146 // an event, then the effect is cumulative i.e. after the call |controller|
147 // will watch both the previous event and the new one.
148 // If an error occurs while calling this method in a cumulative fashion, the
149 // event previously attached to |controller| is aborted.
150 // Returns true on success.
151 // Must be called on the same thread the message_pump is running on.
152 bool WatchFileDescriptor(int fd,
153 bool persistent,
154 Mode mode,
155 FileDescriptorWatcher *controller,
156 Watcher *delegate);
157
158 void RemoveRunLoopSource(CFRunLoopSourceRef source);
159
160 void AddIOObserver(IOObserver* obs);
161 void RemoveIOObserver(IOObserver* obs);
162
64 // Subclasses should implement the work they need to do in MessagePump::Run 163 // Subclasses should implement the work they need to do in MessagePump::Run
65 // in the DoRun method. MessagePumpCFRunLoopBase::Run calls DoRun directly. 164 // in the DoRun method. MessagePumpCFRunLoopBase::Run calls DoRun directly.
66 // This arrangement is used because MessagePumpCFRunLoopBase needs to set 165 // This arrangement is used because MessagePumpCFRunLoopBase needs to set
67 // up and tear down things before and after the "meat" of DoRun. 166 // up and tear down things before and after the "meat" of DoRun.
68 virtual void Run(Delegate* delegate); 167 virtual void Run(Delegate* delegate);
69 virtual void DoRun(Delegate* delegate) = 0; 168 virtual void DoRun(Delegate* delegate) = 0;
70 169
71 virtual void ScheduleWork(); 170 virtual void ScheduleWork();
72 virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time); 171 virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
73 172
74 protected: 173 protected:
75 // Accessors for private data members to be used by subclasses. 174 // Accessors for private data members to be used by subclasses.
76 CFRunLoopRef run_loop() const { return run_loop_; } 175 CFRunLoopRef run_loop() const { return run_loop_; }
77 int nesting_level() const { return nesting_level_; } 176 int nesting_level() const { return nesting_level_; }
78 int run_nesting_level() const { return run_nesting_level_; } 177 int run_nesting_level() const { return run_nesting_level_; }
79 178
80 // Return an autorelease pool to wrap around any work being performed. 179 // Return an autorelease pool to wrap around any work being performed.
81 // In some cases, CreateAutoreleasePool may return nil intentionally to 180 // In some cases, CreateAutoreleasePool may return nil intentionally to
82 // preventing an autorelease pool from being created, allowing any 181 // preventing an autorelease pool from being created, allowing any
83 // objects autoreleased by work to fall into the current autorelease pool. 182 // objects autoreleased by work to fall into the current autorelease pool.
84 virtual NSAutoreleasePool* CreateAutoreleasePool(); 183 virtual NSAutoreleasePool* CreateAutoreleasePool();
85 184
86 private: 185 private:
186 void WillProcessIOEvent();
187 void DidProcessIOEvent();
188
189 static void HandleFdIOEvent(CFFileDescriptorRef fdref,
190 CFOptionFlags callback_types,
191 void* context);
192
87 // Timer callback scheduled by ScheduleDelayedWork. This does not do any 193 // Timer callback scheduled by ScheduleDelayedWork. This does not do any
88 // work, but it signals work_source_ so that delayed work can be performed 194 // work, but it signals work_source_ so that delayed work can be performed
89 // within the appropriate priority constraints. 195 // within the appropriate priority constraints.
90 static void RunDelayedWorkTimer(CFRunLoopTimerRef timer, void* info); 196 static void RunDelayedWorkTimer(CFRunLoopTimerRef timer, void* info);
91 197
92 // Perform highest-priority work. This is associated with work_source_ 198 // Perform highest-priority work. This is associated with work_source_
93 // signalled by ScheduleWork or RunDelayedWorkTimer. The static method calls 199 // signalled by ScheduleWork or RunDelayedWorkTimer. The static method calls
94 // the instance method; the instance method returns true if it resignalled 200 // the instance method; the instance method returns true if it resignalled
95 // work_source_ to be called again from the loop. 201 // work_source_ to be called again from the loop.
96 static void RunWorkSource(void* info); 202 static void RunWorkSource(void* info);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 int deepest_nesting_level_; 283 int deepest_nesting_level_;
178 284
179 // "Delegateless" work flags are set when work is ready to be performed but 285 // "Delegateless" work flags are set when work is ready to be performed but
180 // must wait until a delegate is available to process it. This can happen 286 // must wait until a delegate is available to process it. This can happen
181 // when a MessagePumpCFRunLoopBase is instantiated and work arrives without 287 // when a MessagePumpCFRunLoopBase is instantiated and work arrives without
182 // any call to Run on the stack. The Run method will check for delegateless 288 // any call to Run on the stack. The Run method will check for delegateless
183 // work on entry and redispatch it as needed once a delegate is available. 289 // work on entry and redispatch it as needed once a delegate is available.
184 bool delegateless_work_; 290 bool delegateless_work_;
185 bool delegateless_idle_work_; 291 bool delegateless_idle_work_;
186 292
293 ObserverList<IOObserver> io_observers_;
294 ThreadChecker watch_file_descriptor_caller_checker_;
295
187 DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase); 296 DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase);
188 }; 297 };
189 298
190 class MessagePumpCFRunLoop : public MessagePumpCFRunLoopBase { 299 class MessagePumpCFRunLoop : public MessagePumpCFRunLoopBase {
191 public: 300 public:
192 MessagePumpCFRunLoop(); 301 MessagePumpCFRunLoop();
193 302
194 virtual void DoRun(Delegate* delegate); 303 virtual void DoRun(Delegate* delegate);
195 virtual void Quit(); 304 virtual void Quit();
196 305
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 // thread. Otherwise, returns a new instance of MessagePumpNSRunLoop. 364 // thread. Otherwise, returns a new instance of MessagePumpNSRunLoop.
256 static MessagePump* Create(); 365 static MessagePump* Create();
257 366
258 private: 367 private:
259 DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePumpMac); 368 DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePumpMac);
260 }; 369 };
261 370
262 } // namespace base 371 } // namespace base
263 372
264 #endif // BASE_MESSAGE_PUMP_MAC_H_ 373 #endif // BASE_MESSAGE_PUMP_MAC_H_
OLDNEW
« base/message_loop.cc ('K') | « base/message_loop.cc ('k') | base/message_pump_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698