Index: base/message_pump_mac.h |
=================================================================== |
--- base/message_pump_mac.h (revision 90809) |
+++ base/message_pump_mac.h (working copy) |
@@ -32,6 +32,7 @@ |
#pragma once |
#include "base/message_pump.h" |
+#include "base/observer_list.h" |
#include <CoreFoundation/CoreFoundation.h> |
@@ -58,9 +59,107 @@ |
// Needs access to CreateAutoreleasePool. |
friend class MessagePumpScopedAutoreleasePool; |
public: |
+ class IOObserver { |
+ public: |
+ IOObserver() {} |
+ |
+ // An IOObserver is an object that receives IO notifications from the |
+ // MessagePump. |
+ // |
+ // NOTE: An IOObserver implementation should be extremely fast! |
+ virtual void WillProcessIOEvent() = 0; |
+ virtual void DidProcessIOEvent() = 0; |
+ |
+ protected: |
+ virtual ~IOObserver() {} |
+ }; |
+ |
+ // Used with WatchFileDescptor to asynchronously monitor the I/O readiness of |
+ // a File Descriptor. |
+ class Watcher { |
+ public: |
+ virtual ~Watcher() {} |
+ // Called from MessageLoop::Run when an FD can be read from/written to |
+ // without blocking |
+ virtual void OnFileCanReadWithoutBlocking(int fd) = 0; |
+ virtual void OnFileCanWriteWithoutBlocking(int fd) = 0; |
+ }; |
+ |
+ // Object returned by WatchFileDescriptor to manage further watching. |
+ class FileDescriptorWatcher { |
+ public: |
+ FileDescriptorWatcher(); |
+ ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor. |
+ |
+ // NOTE: These methods aren't called StartWatching()/StopWatching() to |
+ // avoid confusion with the win32 ObjectWatcher class. |
+ |
+ // Stop watching the FD, always safe to call. No-op if there's nothing |
+ // to do. |
+ bool StopWatchingFileDescriptor(); |
+ |
+ private: |
+ friend class MessagePumpCFRunLoopBase; |
+ |
+ // Called by MessagePumpCFRunLoopBase, ownership of |fdref| and |fd_source| |
+ // is transferred to this object. |
+ void Init(CFFileDescriptorRef fdref, |
+ CFOptionFlags callback_types, |
+ CFRunLoopSourceRef fd_source, |
+ bool is_persistent); |
+ |
+ // Used by MessagePumpCFRunLoopBase to take ownership of fdref_. |
+ CFFileDescriptorRef ReleaseCFFileDescriptor(); |
+ |
+ void set_pump(MessagePumpCFRunLoopBase* pump) { pump_ = pump; } |
+ MessagePumpCFRunLoopBase* pump() { return pump_; } |
+ |
+ void set_watcher(Watcher* watcher) { watcher_ = watcher; } |
+ |
+ void OnFileCanReadWithoutBlocking(int fd, MessagePumpCFRunLoopBase* pump); |
+ void OnFileCanWriteWithoutBlocking(int fd, MessagePumpCFRunLoopBase* pump); |
+ |
+ bool is_persistent_; // false if this event is one-shot. |
+ CFFileDescriptorRef fdref_; |
+ CFOptionFlags callback_types_; |
+ CFRunLoopSourceRef fd_source_; |
+ MessagePumpCFRunLoopBase* pump_; |
+ Watcher* watcher_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); |
+ }; |
+ |
+ enum Mode { |
+ WATCH_READ = 1 << 0, |
+ WATCH_WRITE = 1 << 1, |
+ WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE |
+ }; |
+ |
MessagePumpCFRunLoopBase(); |
virtual ~MessagePumpCFRunLoopBase(); |
+ // Have the current thread's message loop watch for a a situation in which |
+ // reading/writing to the FD can be performed without blocking. |
+ // Callers must provide a preallocated FileDescriptorWatcher object which |
+ // can later be used to manage the lifetime of this event. |
+ // If a FileDescriptorWatcher is passed in which is already attached to |
+ // an event, then the effect is cumulative i.e. after the call |controller| |
+ // will watch both the previous event and the new one. |
+ // If an error occurs while calling this method in a cumulative fashion, the |
+ // event previously attached to |controller| is aborted. |
+ // Returns true on success. |
+ // Must be called on the same thread the message_pump is running on. |
+ bool WatchFileDescriptor(int fd, |
+ bool persistent, |
+ Mode mode, |
+ FileDescriptorWatcher *controller, |
+ Watcher *delegate); |
+ |
+ void RemoveRunLoopSource(CFRunLoopSourceRef source); |
+ |
+ void AddIOObserver(IOObserver* obs); |
+ void RemoveIOObserver(IOObserver* obs); |
+ |
// Subclasses should implement the work they need to do in MessagePump::Run |
// in the DoRun method. MessagePumpCFRunLoopBase::Run calls DoRun directly. |
// This arrangement is used because MessagePumpCFRunLoopBase needs to set |
@@ -84,6 +183,13 @@ |
virtual NSAutoreleasePool* CreateAutoreleasePool(); |
private: |
+ void WillProcessIOEvent(); |
+ void DidProcessIOEvent(); |
+ |
+ static void HandleFdIOEvent(CFFileDescriptorRef fdref, |
+ CFOptionFlags callback_types, |
+ void* context); |
+ |
// Timer callback scheduled by ScheduleDelayedWork. This does not do any |
// work, but it signals work_source_ so that delayed work can be performed |
// within the appropriate priority constraints. |
@@ -184,6 +290,9 @@ |
bool delegateless_work_; |
bool delegateless_idle_work_; |
+ ObserverList<IOObserver> io_observers_; |
+ ThreadChecker watch_file_descriptor_caller_checker_; |
+ |
DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase); |
}; |