/core/externals/update-engine/externals/google-toolbox-for-mac/Foundation/GTMAbstractDOListener.h
C++ Header | 231 lines | 48 code | 23 blank | 160 comment | 0 complexity | faa0e785464bd824f9a2b32579f44190 MD5 | raw file
1// 2// GTMAbstractDOListener.h 3// 4// Copyright 2006-2009 Google Inc. 5// 6// Licensed under the Apache License, Version 2.0 (the "License"); you may not 7// use this file except in compliance with the License. You may obtain a copy 8// of the License at 9// 10// http://www.apache.org/licenses/LICENSE-2.0 11// 12// Unless required by applicable law or agreed to in writing, software 13// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15// License for the specific language governing permissions and limitations under 16// the License. 17// 18#import <Foundation/Foundation.h> 19#import "GTMDefines.h" 20 21#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 22@class GTMReceivePortDelegate; 23#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 24 25// Abstract base class for DO "listeners". 26// A class that needs to vend itself over DO should subclass this abstract 27// class. This class takes care of certain things like creating a new thread 28// to handle requests, setting request/reply timeouts, and ensuring the vended 29// object only gets requests that comply with the specified protocol. 30// 31// Subclassers will want to use the 32// GTM_ABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL macro for easier debugging 33// of stack traces. Please read it's description below. 34// 35@interface GTMAbstractDOListener : NSObject <NSConnectionDelegate> { 36 @protected 37 NSString *registeredName_; 38 __weak Protocol *protocol_; 39 NSConnection *connection_; 40 BOOL isRunningInNewThread_; 41 BOOL shouldShutdown_; 42 NSTimeInterval requestTimeout_; 43 NSTimeInterval replyTimeout_; 44 NSPort *port_; 45 NSTimeInterval heartRate_; 46 47#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 48 GTMReceivePortDelegate *receivePortDelegate_; // Strong (only used on Tiger) 49#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 50} 51 52// Returns a set of all live instances of GTMAbstractDOListener subclasses. 53// If no listeners have been created, this will return an empty array--not nil. 54// 55// TODO: Remove this method 56// 57+ (NSArray *)allListeners; 58 59// Initializer. This actually calls 60// initWithRegisteredName:protocol:port with [NSMachPort port] as the port. 61// 62// Args: 63// name - the name that the object will register under 64// proto - the protocol that this object (self) should conform to 65// 66- (id)initWithRegisteredName:(NSString *)name protocol:(Protocol *)proto; 67 68// The designated initializer. 69// 70// Args: 71// name - the name used to register the port. While not necessarily required 72// for an NSSocketPort this class still requires it. 73// proto - the protocol that this object (self) should conform to 74// port - the port to be used when creating the NSConnection. If a NSMachPort 75// is being used then initWithRegisteredName:protocol is recommended. 76// Otherwise the port must be allocted by the caller. 77// 78- (id)initWithRegisteredName:(NSString *)name 79 protocol:(Protocol *)proto 80 port:(NSPort *)port; 81 82// Returns the name that this server will register with the 83// mach port name sever. This is the name of the port that this class 84// will "listen" on when -runInNewThread is called. 85// 86// Returns: 87// The registered name as a string 88// 89- (NSString *)registeredName; 90 91// Sets the registered name to use when listening over DO. This only makes 92// sense to be called before -runInNewThread has been called, because 93// -runInNewThread will listen on this "registered name", so setting it 94// afterwards would do nothing. 95// 96// Args: 97// name - the name to register under. May not be nil. 98// 99- (void)setRegisteredName:(NSString *)name; 100 101// Get/set the request timeout interval. If set to a value less than 0, 102// the default DO connection timeout will be used (maximum possible value). 103// 104- (NSTimeInterval)requestTimeout; 105- (void)setRequestTimeout:(NSTimeInterval)timeout; 106 107// Get/set the reply timeout interval. If set to a value less than 0, 108// the default DO connection timeout will be used (maximum possible value). 109// 110- (NSTimeInterval)replyTimeout; 111- (void)setReplyTimeout:(NSTimeInterval)timeout; 112 113// Get/set how long the thread will spin the run loop. This only takes affect 114// if runInNewThreadWithErrorTarget:selector:withObjectArgument: is used. The 115// default heart rate is 10.0 seconds. 116// 117- (void)setThreadHeartRate:(NSTimeInterval)heartRate; 118- (NSTimeInterval)ThreadHeartRate; 119 120// Returns the listeners associated NSConnection. May be nil if no connection 121// has been setup yet. 122// 123- (NSConnection *)connection; 124 125// Starts the DO system listening using the current thread and current runloop. 126// It only makes sense to call this method -OR- -runInNewThread, but not both. 127// Returns YES if it was able to startup the DO listener, NO otherwise. 128// 129- (BOOL)runInCurrentThread; 130 131// Starts the DO system listening, and creates a new thread to handle the DO 132// connections. It only makes sense to call this method -OR- 133// -runInCurrentThread, but not both. 134// if |errObject| is non nil, it will be used along with |selector| and 135// |argument| to signal that the startup of the listener in the new thread 136// failed. The actual selector will be invoked back on the main thread so 137// it does not have to be thread safe. 138// The most basic way to call this method is as follows: 139// [listener runInNewThreadWithErrorTarget:nil 140// selector:NULL 141// withObjectArgument:nil]; 142// 143// Note: Using the example above you will not know if the listener failed to 144// startup due to some error. 145// 146- (void)runInNewThreadWithErrorTarget:(id)errObject 147 selector:(SEL)selector 148 withObjectArgument:(id)argument; 149 150// Shuts down the connection. If it was running in a new thread, that thread 151// should exit (within about 10 seconds). This call does not block. 152// 153// NOTE: This method is called in -dealloc, so if -runInNewThread had previously 154// been called, -dealloc will return *before* the thread actually exits. This 155// can be a problem as "self" may be gone before the thread exits. This is a 156// bug and needs to be fixed. Currently, to be safe, only call -shutdown if 157// -runInCurrentThread had previously been called. 158// 159- (void)shutdown; 160 161@end 162 163 164// Methods that subclasses may implement to vary the behavior of this abstract 165// class. 166// 167@interface GTMAbstractDOListener (GTMAbstractDOListenerSubclassMethods) 168 169// Called by the -runIn* methods. In the case where a new thread is being used, 170// this method is called on the new thread. The default implementation of this 171// method just returns YES, but subclasses can override it to do subclass 172// specific initialization. If this method returns NO, the -runIn* method that 173// called it will fail with an error. 174// 175// Returns: 176// YES if the -runIn* method should continue successfully, NO if the it should 177// fail. 178// 179- (BOOL)doRunInitialization; 180 181// Called as the "main" for the thread spun off by GTMAbstractDOListener. 182// Not really for use by subclassers, except to use the 183// GTMABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL macro defined below. 184// 185// This method runs forever in a new thread. This method actually starts the 186// DO connection listening. 187// 188- (void)threadMain:(NSInvocation *)failureCallback; 189 190@end 191 192// GTMAbstractDOListeners used to be hard to debug because crashes in their 193// stacks looked like this: 194// 195// #0 0x90009cd7 in mach_msg_trap () 196// #1 0x90009c38 in mach_msg () 197// #2 0x9082d2b3 in CFRunLoopRunSpecific () 198// #3 0x9082cace in CFRunLoopRunInMode () 199// #4 0x9282ad3a in -[NSRunLoop runMode:beforeDate:] () 200// #5 0x928788e4 in -[NSRunLoop runUntilDate:] () 201// #6 0x00052696 in -[GTMAbstractDOListener(GTMAbstractDOListenerSubclassMethods) threadMain:] ... 202// #7 0x927f52e0 in forkThreadForFunction () 203// #8 0x90024227 in _pthread_body () 204// 205// and there was no good way to figure out what thread had the problem because 206// they all originated from 207// -[GTMAbstractDOListener(GTMAbstractDOListenerSubclassMethods) threadMain:] 208// 209// If you add GTMABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL to the impl of your 210// subclass you will get a stack that looks like this: 211// #0 0x90009cd7 in mach_msg_trap () 212// #1 0x90009c38 in mach_msg () 213// #2 0x9082d2b3 in CFRunLoopRunSpecific () 214// #3 0x9082cace in CFRunLoopRunInMode () 215// #4 0x9282ad3a in -[NSRunLoop runMode:beforeDate:] () 216// #5 0x928788e4 in -[NSRunLoop runUntilDate:] () 217// #6 0x00052696 in -[GTMAbstractDOListener(GTMAbstractDOListenerSubclassMethods) threadMain:] ... 218// #7 0x0004b35c in -[GDStatsListener threadMain:] 219// #8 0x927f52e0 in forkThreadForFunction () #9 0x90024227 in _pthread_body () 220// 221// so we can see that this was the GDStatsListener thread that failed. 222// It will look something like this 223// @implemetation MySubclassOfGTMAbstractDOListenerSubclassMethods 224// GTM_ABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL 225// .... 226// @end 227 228#define GTM_ABSTRACTDOLISTENER_SUBCLASS_THREADMAIN_IMPL \ 229 - (void)threadMain:(NSInvocation *)failureCallback { \ 230 [super threadMain:failureCallback]; \ 231 }