OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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_ |
OLD | NEW |