1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/message_pump_mac.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,275 @@ 1.4 +// Copyright (c) 2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +// The basis for all native run loops on the Mac is the CFRunLoop. It can be 1.9 +// used directly, it can be used as the driving force behind the similar 1.10 +// Foundation NSRunLoop, and it can be used to implement higher-level event 1.11 +// loops such as the NSApplication event loop. 1.12 +// 1.13 +// This file introduces a basic CFRunLoop-based implementation of the 1.14 +// MessagePump interface called CFRunLoopBase. CFRunLoopBase contains all 1.15 +// of the machinery necessary to dispatch events to a delegate, but does not 1.16 +// implement the specific run loop. Concrete subclasses must provide their 1.17 +// own DoRun and Quit implementations. 1.18 +// 1.19 +// A concrete subclass that just runs a CFRunLoop loop is provided in 1.20 +// MessagePumpCFRunLoop. For an NSRunLoop, the similar MessagePumpNSRunLoop 1.21 +// is provided. 1.22 +// 1.23 +// For the application's event loop, an implementation based on AppKit's 1.24 +// NSApplication event system is provided in MessagePumpNSApplication. 1.25 +// 1.26 +// Typically, MessagePumpNSApplication only makes sense on a Cocoa 1.27 +// application's main thread. If a CFRunLoop-based message pump is needed on 1.28 +// any other thread, one of the other concrete subclasses is preferrable. 1.29 +// MessagePumpMac::Create is defined, which returns a new NSApplication-based 1.30 +// or NSRunLoop-based MessagePump subclass depending on which thread it is 1.31 +// called on. 1.32 + 1.33 +#ifndef BASE_MESSAGE_PUMP_MAC_H_ 1.34 +#define BASE_MESSAGE_PUMP_MAC_H_ 1.35 + 1.36 +#include "base/message_pump.h" 1.37 + 1.38 +#include <CoreFoundation/CoreFoundation.h> 1.39 +#include <IOKit/IOKitLib.h> 1.40 + 1.41 +#if defined(__OBJC__) 1.42 +@class NSAutoreleasePool; 1.43 +#else // defined(__OBJC__) 1.44 +class NSAutoreleasePool; 1.45 +#endif // defined(__OBJC__) 1.46 + 1.47 +namespace base { 1.48 + 1.49 +class TimeTicks; 1.50 + 1.51 +class MessagePumpCFRunLoopBase : public MessagePump { 1.52 + // Needs access to CreateAutoreleasePool. 1.53 + friend class MessagePumpScopedAutoreleasePool; 1.54 + public: 1.55 + MessagePumpCFRunLoopBase(); 1.56 + virtual ~MessagePumpCFRunLoopBase(); 1.57 + 1.58 + // Subclasses should implement the work they need to do in MessagePump::Run 1.59 + // in the DoRun method. MessagePumpCFRunLoopBase::Run calls DoRun directly. 1.60 + // This arrangement is used because MessagePumpCFRunLoopBase needs to set 1.61 + // up and tear down things before and after the "meat" of DoRun. 1.62 + virtual void Run(Delegate* delegate); 1.63 + virtual void DoRun(Delegate* delegate) = 0; 1.64 + 1.65 + virtual void ScheduleWork(); 1.66 + virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time); 1.67 + 1.68 + protected: 1.69 + // Accessors for private data members to be used by subclasses. 1.70 + CFRunLoopRef run_loop() const { return run_loop_; } 1.71 + int nesting_level() const { return nesting_level_; } 1.72 + int run_nesting_level() const { return run_nesting_level_; } 1.73 + 1.74 + // Return an autorelease pool to wrap around any work being performed. 1.75 + // In some cases, CreateAutoreleasePool may return nil intentionally to 1.76 + // preventing an autorelease pool from being created, allowing any 1.77 + // objects autoreleased by work to fall into the current autorelease pool. 1.78 + virtual NSAutoreleasePool* CreateAutoreleasePool(); 1.79 + 1.80 + private: 1.81 + // Timer callback scheduled by ScheduleDelayedWork. This does not do any 1.82 + // work, but it signals delayed_work_source_ so that delayed work can be 1.83 + // performed within the appropriate priority constraints. 1.84 + static void RunDelayedWorkTimer(CFRunLoopTimerRef timer, void* info); 1.85 + 1.86 + // Perform highest-priority work. This is associated with work_source_ 1.87 + // signalled by ScheduleWork. The static method calls the instance method; 1.88 + // the instance method returns true if work was done. 1.89 + static void RunWorkSource(void* info); 1.90 + bool RunWork(); 1.91 + 1.92 + // Perform delayed-priority work. This is associated with 1.93 + // delayed_work_source_ signalled by RunDelayedWorkTimer, and is responsible 1.94 + // for calling ScheduleDelayedWork again if appropriate. The static method 1.95 + // calls the instance method; the instance method returns true if more 1.96 + // delayed work is available. 1.97 + static void RunDelayedWorkSource(void* info); 1.98 + bool RunDelayedWork(); 1.99 + 1.100 + // Perform idle-priority work. This is normally called by PreWaitObserver, 1.101 + // but is also associated with idle_work_source_. When this function 1.102 + // actually does perform idle work, it will resignal that source. The 1.103 + // static method calls the instance method; the instance method returns 1.104 + // true if idle work was done. 1.105 + static void RunIdleWorkSource(void* info); 1.106 + bool RunIdleWork(); 1.107 + 1.108 + // Perform work that may have been deferred because it was not runnable 1.109 + // within a nested run loop. This is associated with 1.110 + // nesting_deferred_work_source_ and is signalled by 1.111 + // MaybeScheduleNestingDeferredWork when returning from a nested loop, 1.112 + // so that an outer loop will be able to perform the necessary tasks if it 1.113 + // permits nestable tasks. 1.114 + static void RunNestingDeferredWorkSource(void* info); 1.115 + bool RunNestingDeferredWork(); 1.116 + 1.117 + // Schedules possible nesting-deferred work to be processed before the run 1.118 + // loop goes to sleep, exits, or begins processing sources at the top of its 1.119 + // loop. If this function detects that a nested loop had run since the 1.120 + // previous attempt to schedule nesting-deferred work, it will schedule a 1.121 + // call to RunNestingDeferredWorkSource. 1.122 + void MaybeScheduleNestingDeferredWork(); 1.123 + 1.124 + // Observer callback responsible for performing idle-priority work, before 1.125 + // the run loop goes to sleep. Associated with idle_work_observer_. 1.126 + static void PreWaitObserver(CFRunLoopObserverRef observer, 1.127 + CFRunLoopActivity activity, void* info); 1.128 + 1.129 + // Observer callback called before the run loop processes any sources. 1.130 + // Associated with pre_source_observer_. 1.131 + static void PreSourceObserver(CFRunLoopObserverRef observer, 1.132 + CFRunLoopActivity activity, void* info); 1.133 + 1.134 + // Observer callback called when the run loop starts and stops, at the 1.135 + // beginning and end of calls to CFRunLoopRun. This is used to maintain 1.136 + // nesting_level_. Associated with enter_exit_observer_. 1.137 + static void EnterExitObserver(CFRunLoopObserverRef observer, 1.138 + CFRunLoopActivity activity, void* info); 1.139 + 1.140 + // Called by EnterExitObserver after performing maintenance on nesting_level_. 1.141 + // This allows subclasses an opportunity to perform additional processing on 1.142 + // the basis of run loops starting and stopping. 1.143 + virtual void EnterExitRunLoop(CFRunLoopActivity activity); 1.144 + 1.145 + // IOKit power state change notification callback, called when the system 1.146 + // enters and leaves the sleep state. 1.147 + static void PowerStateNotification(void* info, io_service_t service, 1.148 + uint32_t message_type, 1.149 + void* message_argument); 1.150 + 1.151 + // The thread's run loop. 1.152 + CFRunLoopRef run_loop_; 1.153 + 1.154 + // The timer, sources, and observers are described above alongside their 1.155 + // callbacks. 1.156 + CFRunLoopTimerRef delayed_work_timer_; 1.157 + CFRunLoopSourceRef work_source_; 1.158 + CFRunLoopSourceRef delayed_work_source_; 1.159 + CFRunLoopSourceRef idle_work_source_; 1.160 + CFRunLoopSourceRef nesting_deferred_work_source_; 1.161 + CFRunLoopObserverRef pre_wait_observer_; 1.162 + CFRunLoopObserverRef pre_source_observer_; 1.163 + CFRunLoopObserverRef enter_exit_observer_; 1.164 + 1.165 + // Objects used for power state notification. See PowerStateNotification. 1.166 + io_connect_t root_power_domain_; 1.167 + IONotificationPortRef power_notification_port_; 1.168 + io_object_t power_notification_object_; 1.169 + 1.170 + // (weak) Delegate passed as an argument to the innermost Run call. 1.171 + Delegate* delegate_; 1.172 + 1.173 + // The time that delayed_work_timer_ is scheduled to fire. This is tracked 1.174 + // independently of CFRunLoopTimerGetNextFireDate(delayed_work_timer_) 1.175 + // to be able to reset the timer properly after waking from system sleep. 1.176 + // See PowerStateNotification. 1.177 + CFAbsoluteTime delayed_work_fire_time_; 1.178 + 1.179 + // The recursion depth of the currently-executing CFRunLoopRun loop on the 1.180 + // run loop's thread. 0 if no run loops are running inside of whatever scope 1.181 + // the object was created in. 1.182 + int nesting_level_; 1.183 + 1.184 + // The recursion depth (calculated in the same way as nesting_level_) of the 1.185 + // innermost executing CFRunLoopRun loop started by a call to Run. 1.186 + int run_nesting_level_; 1.187 + 1.188 + // The deepest (numerically highest) recursion depth encountered since the 1.189 + // most recent attempt to run nesting-deferred work. 1.190 + int deepest_nesting_level_; 1.191 + 1.192 + // "Delegateless" work flags are set when work is ready to be performed but 1.193 + // must wait until a delegate is available to process it. This can happen 1.194 + // when a MessagePumpCFRunLoopBase is instantiated and work arrives without 1.195 + // any call to Run on the stack. The Run method will check for delegateless 1.196 + // work on entry and redispatch it as needed once a delegate is available. 1.197 + bool delegateless_work_; 1.198 + bool delegateless_delayed_work_; 1.199 + bool delegateless_idle_work_; 1.200 + 1.201 + DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase); 1.202 +}; 1.203 + 1.204 +class MessagePumpCFRunLoop : public MessagePumpCFRunLoopBase { 1.205 + public: 1.206 + MessagePumpCFRunLoop(); 1.207 + 1.208 + virtual void DoRun(Delegate* delegate); 1.209 + virtual void Quit(); 1.210 + 1.211 + private: 1.212 + virtual void EnterExitRunLoop(CFRunLoopActivity activity); 1.213 + 1.214 + // True if Quit is called to stop the innermost MessagePump 1.215 + // (innermost_quittable_) but some other CFRunLoopRun loop (nesting_level_) 1.216 + // is running inside the MessagePump's innermost Run call. 1.217 + bool quit_pending_; 1.218 + 1.219 + DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoop); 1.220 +}; 1.221 + 1.222 +class MessagePumpNSRunLoop : public MessagePumpCFRunLoopBase { 1.223 + public: 1.224 + MessagePumpNSRunLoop(); 1.225 + virtual ~MessagePumpNSRunLoop(); 1.226 + 1.227 + virtual void DoRun(Delegate* delegate); 1.228 + virtual void Quit(); 1.229 + 1.230 + private: 1.231 + // A source that doesn't do anything but provide something signalable 1.232 + // attached to the run loop. This source will be signalled when Quit 1.233 + // is called, to cause the loop to wake up so that it can stop. 1.234 + CFRunLoopSourceRef quit_source_; 1.235 + 1.236 + // False after Quit is called. 1.237 + bool keep_running_; 1.238 + 1.239 + DISALLOW_COPY_AND_ASSIGN(MessagePumpNSRunLoop); 1.240 +}; 1.241 + 1.242 +class MessagePumpNSApplication : public MessagePumpCFRunLoopBase { 1.243 + public: 1.244 + MessagePumpNSApplication(); 1.245 + 1.246 + virtual void DoRun(Delegate* delegate); 1.247 + virtual void Quit(); 1.248 + 1.249 + protected: 1.250 + // Returns nil if NSApp is currently in the middle of calling -sendEvent. 1.251 + virtual NSAutoreleasePool* CreateAutoreleasePool(); 1.252 + 1.253 + private: 1.254 + // False after Quit is called. 1.255 + bool keep_running_; 1.256 + 1.257 + // True if DoRun is managing its own run loop as opposed to letting 1.258 + // -[NSApplication run] handle it. The outermost run loop in the application 1.259 + // is managed by -[NSApplication run], inner run loops are handled by a loop 1.260 + // in DoRun. 1.261 + bool running_own_loop_; 1.262 + 1.263 + DISALLOW_COPY_AND_ASSIGN(MessagePumpNSApplication); 1.264 +}; 1.265 + 1.266 +class MessagePumpMac { 1.267 + public: 1.268 + // Returns a new instance of MessagePumpNSApplication if called on the main 1.269 + // thread. Otherwise, returns a new instance of MessagePumpNSRunLoop. 1.270 + static MessagePump* Create(); 1.271 + 1.272 + private: 1.273 + DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePumpMac); 1.274 +}; 1.275 + 1.276 +} // namespace base 1.277 + 1.278 +#endif // BASE_MESSAGE_PUMP_MAC_H_