Changeset 3713
- Timestamp:
- 08/15/07 10:58:11 (1 year ago)
- Files:
-
- trunk/Chat Core/InterThreadMessaging.h (modified) (1 diff)
- trunk/Chat Core/InterThreadMessaging.m (modified) (2 diffs)
- trunk/Chat Core/MVDirectClientConnection.h (modified) (2 diffs)
- trunk/Chat Core/MVDirectClientConnection.m (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Chat Core/InterThreadMessaging.h
r3150 r3713 1 /*-*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-*/2 1 /* 3 2 * InterThreadMessaging -- InterThreadMessaging.h 4 3 * Created by toby on Tue Jun 19 2001. 5 *6 * A low-cost-but-not-quite-as-general alternative to D.O.7 *8 4 */ 9 5 10 #import <Foundation/Foundation.h>11 12 13 6 @interface NSThread (InterThreadMessaging) 14 15 /* The inter-thread messaging category methods use NSPorts to deliver messages 16 between threads. In order to receive an inter-thread message, the receiver 17 must both (1) be running a run loop; and (2) be monitoring this port in its 18 run loop. You must call this method from the context of the thread you wish 19 to prepare for inter-thread messages (which is why these are class methods). 20 21 Before a thread can receive any inter-thread messages, it must invoke one 22 of the following methods to prepare the thread and its run loop to receive 23 these messages. In order to process a message from another thread, the 24 receiving thread must, of course, be running its run loop. */ 25 26 + (void) prepareForInterThreadMessages; // in NSDefaultRunLoopMode 27 7 + (void) prepareForInterThreadMessages; 28 8 @end 29 9 30 31 32 /* Invoke in the specified thread a method on an object. The target33 thread must have been readied for inter-thread messages by invoking34 +prepareForInterThreadMessages. It must be running its run loop in35 order to receive the messages.36 37 In some situations, a sender may be able to blast messages to an object38 faster than they can be processed in the target thread. To prevent things39 from spiraling out of control, the underlying NSPorts implement a throtling40 mechanism in the form of a fixed queue size. When this queue is filled, all41 further messages are rejected until until a message has been pulled off the42 queue. The sender may specify a limit date; if the queue is full, the43 sender will block until this limit date expires or until space is made in44 the queue. An NSPortTimeoutException exception is thrown if the limit date45 expires (or if no limit date is specified) before the message can be46 delivered.47 48 There is one very important point to watch out for: to prevent heinously49 difficult to debug memory smashers, the receing object and all of its50 arguments are retained in the context of the sending thread. When the51 message has been delivered in the target thread, these objects are auto-52 released IN THE CONTEXT OF THE TARGET THREAD. Thus, it is possible for53 the objects to be deallocated in a thread different from the one they were54 allocated in. (In general, you don't need to worry about simple/immutable55 objects, such as NSString, NSData, etc.) */56 57 10 @interface NSObject (InterThreadMessaging) 58 59 - (void) performSelector:(SEL)selector 60 inThread:(NSThread *)thread; // before date [NSDate distantFuture] 61 62 - (void) performSelector:(SEL)selector 63 inThread:(NSThread *)thread 64 beforeDate:(NSDate *)limitDate; 65 66 - (void) performSelector:(SEL)selector 67 withObject:(id)object 68 inThread:(NSThread *)thread; // before date [NSDate distantFuture] 69 70 - (void) performSelector:(SEL)selector 71 withObject:(id)object 72 inThread:(NSThread *)thread 73 beforeDate:(NSDate *)limitDate; 74 75 - (void) performSelector:(SEL)selector 76 withObject:(id)object1 77 withObject:(id)object2 78 inThread:(NSThread *)thread; // before date [NSDate distantFuture] 79 80 - (void) performSelector:(SEL)selector 81 withObject:(id)object1 82 withObject:(id)object2 83 inThread:(NSThread *)thread 84 beforeDate:(NSDate *)limitDate; 85 11 - (void) performSelector:(SEL)selector inThread:(NSThread *)thread; 12 - (void) performSelector:(SEL)selector inThread:(NSThread *)thread waitUntilDone:(BOOL)wait; 13 - (void) performSelector:(SEL)selector withObject:(id)object inThread:(NSThread *)thread; 14 - (void) performSelector:(SEL)selector withObject:(id)object inThread:(NSThread *)thread waitUntilDone:(BOOL)wait; 86 15 @end 87 88 89 90 91 /* Post a notification in the specified thread. The target thread must92 have been readied for inter-thread messages by sending itself the93 +prepareForInterThreadMessages. It must be running its run loop in94 order to receive the messages.95 96 In some situations, a sender may be able to blast messages to an object97 faster than they can be processed in the target thread. To prevent things98 from spiraling out of control, the underlying NSPorts implement a throtling99 mechanism in the form of a fixed queue size. When this queue is filled, all100 further messages are rejected until until a message has been pulled off the101 queue. The sender may specify a limit date; if the queue is full, the102 sender will block until this limit date expires or until space is made in103 the queue. An NSPortTimeoutException exception is thrown if the limit date104 expires (or if no limit date is specified) before the message can be105 delivered.106 107 There is one very important point to watch out for: to prevent heinously108 difficult to debug memory smashers, the notification object (and109 consequently the userInfo dictionary) are retained in the context of110 the sending thread. When the message has been delivered in the target111 thread, the notification object is auto-released IN THE CONTEXT OF THE112 TARGET THREAD. Thus, it is possible for objects to be deallocated in a113 thread different from the one they were allocated in. (In general, you114 don't need to worry about simple/immutable objects, such as NSString,115 NSData, etc.) */116 117 @interface NSNotificationCenter (InterThreadMessaging)118 119 - (void) postNotification:(NSNotification *)notification120 inThread:(NSThread *)thread; // before date [NSDate distantFuture]121 122 - (void) postNotification:(NSNotification *)notification123 inThread:(NSThread *)thread124 beforeDate:(NSDate *)limitDate;125 126 - (void) postNotificationName:(NSString *)name127 object:(id)object128 inThread:(NSThread *)thread; // before date [NSDate distantFuture]129 130 - (void) postNotificationName:(NSString *)name131 object:(id)object132 inThread:(NSThread *)thread133 beforeDate:(NSDate *)limitDate;134 135 - (void) postNotificationName:(NSString *)name136 object:(id)object137 userInfo:(NSDictionary *)userInfo138 inThread:(NSThread *)thread; // before date [NSDate distantFuture]139 140 - (void) postNotificationName:(NSString *)name141 object:(id)object142 userInfo:(NSDictionary *)userInfo143 inThread:(NSThread *)thread144 beforeDate:(NSDate *)limitDate;145 146 @end147 trunk/Chat Core/InterThreadMessaging.m
r3710 r3713 1 /*-*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-*/2 1 /* 3 2 * InterThreadMessaging -- InterThreadMessaging.m 4 3 * Created by toby on Tue Jun 19 2001. 5 *6 4 */ 7 5 8 #import <pthread.h>9 6 #import "InterThreadMessaging.h" 10 7 8 @interface NSObject (LeopardOnly) 9 - (void) performSelector:(SEL) selector onThread:(NSThread *) thread withObject:(id) object waitUntilDone:(BOOL) wait; 10 @end 11 11 12 /* There are four types of messages that can be posted between threads: a 13 notification to be posted to the default notification centre and selectors 14 to be performed with a varying number of arguments. (I was tempted to 15 implement all three in terms of performSelector:withObject:withObject: 16 and passing in nil for the empty arguments, but then it occurred to me 17 that perhaps the receiver has overridden performSelector: and 18 performSelector:withObject:. So I think I must disambiguate between 19 them all.) */ 12 static BOOL useSystemThreadPerformSelector() { 13 static BOOL useSystemVersion = NO; 14 static BOOL checkedSystem = NO; 20 15 21 typedef enum InterThreadMessageType InterThreadMessageType; 22 enum InterThreadMessageType 23 { 24 kITMPostNotification = 1, 25 kITMPerformSelector0Args, 26 kITMPerformSelector1Args, 27 kITMPerformSelector2Args 28 }; 16 if( ! checkedSystem ) { 17 useSystemVersion = [NSObject instancesRespondToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]; 18 checkedSystem = YES; 19 } 29 20 21 return useSystemVersion; 22 } 30 23 31 /* The message contents are carried between threads in this struct. The 32 struct is allocated in the sending thread and freed in the receiving thread. 33 It is carried between the threads in an NSPortMessage - the NSPortMessage 34 contains a single NSData argument, which is a wrapper around the pointer to 35 this struct. */ 24 #import <pthread.h> 36 25 37 typedef struct InterThreadMessage InterThreadMessage; 38 struct InterThreadMessage 39 { 40 InterThreadMessageType type; 41 union { 42 NSNotification *notification; 43 struct { 44 SEL selector; 45 id receiver; 46 id arg1; 47 id arg2; 48 } sel; 49 } data; 50 }; 51 52 53 54 /* Each thread is associated with an NSPort. This port is used to deliver 55 messages to the target thread. */ 26 typedef struct InterThreadMessage { 27 SEL selector; 28 id receiver; 29 id arg; 30 } InterThreadMessage; 56 31 57 32 static NSMapTable *pThreadMessagePorts = NULL; 58 static NSMapTable *pThreadRunLoops = NULL;59 33 static pthread_mutex_t pGate; 60 34 … … 64 38 @end 65 39 66 static void 67 createMessagePortForThread (NSThread *thread, NSRunLoop *runLoop) 68 { 69 NSPort *port; 40 static void createMessagePortForThread(NSThread *thread, NSRunLoop *runLoop) { 41 pthread_mutex_lock(&pGate); 70 42 71 assert(nil != thread); 72 assert(nil != runLoop); 73 assert(NULL != pThreadMessagePorts); 74 assert(NULL != pThreadRunLoops); 43 NSPort *port = NSMapGet(pThreadMessagePorts, thread); 44 if( ! port ) { 45 port = [[NSPort allocWithZone:NULL] init]; 46 [port setDelegate:[InterThreadManager class]]; 47 [port scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode]; 75 48 76 pthread_mutex_lock(&pGate); 49 NSMapInsertKnownAbsent(pThreadMessagePorts, thread, port); 50 [port release]; 51 } 77 52 78 port = NSMapGet(pThreadMessagePorts, thread); 79 if (nil == port) { 80 port = [[NSPort allocWithZone:NULL] init]; 81 [port setDelegate:[InterThreadManager class]]; 82 [port scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode]; 83 NSMapInsertKnownAbsent(pThreadMessagePorts, thread, port); 84 NSMapInsertKnownAbsent(pThreadRunLoops, thread, runLoop); 85 86 /* Transfer ownership of this port to the map table. */ 87 [port release]; 88 } 89 90 pthread_mutex_unlock(&pGate); 53 pthread_mutex_unlock(&pGate); 91 54 } 92 55 93 static NSPort * 94 messagePortForThread (NSThread *thread) 95 { 96 NSPort *port;56 static NSPort *messagePortForThread(NSThread *thread) { 57 pthread_mutex_lock(&pGate); 58 NSPort *port = NSMapGet(pThreadMessagePorts, thread); 59 pthread_mutex_unlock(&pGate); 97 60 98 assert(nil != thread); 99 assert(NULL != pThreadMessagePorts); 61 if( ! port ) [NSException raise:NSInvalidArgumentException format:@"Thread %@ is not prepared to receive inter-thread messages. You must invoke +prepareForInterThreadMessages first.", thread]; 100 62 101 pthread_mutex_lock(&pGate); 102 port = NSMapGet(pThreadMessagePorts, thread); 103 pthread_mutex_unlock(&pGate); 104 105 if (nil == port) { 106 [NSException raise:NSInvalidArgumentException 107 format:@"Thread %@ is not prepared to receive " 108 @"inter-thread messages. You must invoke " 109 @"+prepareForInterThreadMessages first.", thread]; 110 } 111 112 return port; 63 return port; 113 64 } 114 65 115 static void 116 removeMessagePortForThread (NSThread *thread) 117 { 118 NSPort *port; 66 static void removeMessagePortForThread(NSThread *thread) { 67 pthread_mutex_lock(&pGate); 119 68 120 assert(nil != thread); 121 assert(NULL != pThreadMessagePorts); 69 NSPort *port = (NSPort *) NSMapGet(pThreadMessagePorts, thread); 70 if (port) { 71 [port invalidate]; 72 NSMapRemove(pThreadMessagePorts, thread); 73 } 122 74 123 pthread_mutex_lock(&pGate); 124 125 port = (NSPort *) NSMapGet(pThreadMessagePorts, thread); 126 if (nil != port) { 127 NSRunLoop *runLoop = NSMapGet(pThreadRunLoops, thread); 128 [port removeFromRunLoop:runLoop forMode:NSDefaultRunLoopMode]; 129 NSMapRemove(pThreadRunLoops, thread); 130 NSMapRemove(pThreadMessagePorts, thread); 131 } 132 133 pthread_mutex_unlock(&pGate); 75 pthread_mutex_unlock(&pGate); 134 76 } 135 77 78 @implementation NSThread (InterThreadMessaging) 79 + (void) prepareForInterThreadMessages { 80 if(useSystemThreadPerformSelector()) 81 return; 82 [InterThreadManager class]; // Force the class initialization. 83 createMessagePortForThread([NSThread currentThread], [NSRunLoop currentRunLoop]); 84 } 85 @end 136 86 137 138 139 @implementation NSThread (InterThreadMessaging) 140 141 + (void) prepareForInterThreadMessages 142 { 143 /* Force the class initialization. */ 144 [InterThreadManager class]; 145 146 createMessagePortForThread([NSThread currentThread], 147 [NSRunLoop currentRunLoop]); 87 @implementation InterThreadManager 88 + (void) initialize { 89 if(useSystemThreadPerformSelector()) 90 return; 91 if( ! pThreadMessagePorts ) { 92 pthread_mutex_init(&pGate, NULL); 93 pThreadMessagePorts = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 0); 94 [[NSNotificationCenter defaultCenter] addObserver:[self class] selector:@selector(threadDied:) name:NSThreadWillExitNotification object:nil]; 95 } 148 96 } 149 97 98 + (void) threadDied:(NSNotification *)notification { 99 removeMessagePortForThread([notification object]); 100 } 101 102 + (void) handlePortMessage:(NSPortMessage *)portMessage { 103 NSArray *components = [portMessage components]; 104 NSData *data = [components objectAtIndex:0]; 105 InterThreadMessage *msg = *((InterThreadMessage **) [data bytes]); 106 107 [msg->receiver performSelector:msg->selector withObject:msg->arg]; 108 109 [msg->receiver release]; 110 [msg->arg release]; 111 112 free(msg); 113 } 150 114 @end 151 115 152 153 154 155 @implementation InterThreadManager 156 157 + (void) initialize 158 { 159 /* Create the mutex - this should be invoked by the Objective-C runtime 160 (in a thread-safe manner) before any one can use this module, so I 161 don't think I need to worry about race conditions here. */ 162 if (nil == pThreadMessagePorts) { 163 pthread_mutex_init(&pGate, NULL); 164 165 pThreadMessagePorts = 166 NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, 167 NSObjectMapValueCallBacks, 0); 168 pThreadRunLoops = 169 NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, 170 NSObjectMapValueCallBacks, 0); 171 172 [[NSNotificationCenter defaultCenter] 173 addObserver:[self class] 174 selector:@selector(threadDied:) 175 name:NSThreadWillExitNotification 176 object:nil]; 177 } 178 } 179 180 + (void) threadDied:(NSNotification *)notification 181 { 182 removeMessagePortForThread([notification object]); 183 } 184 185 + (void) handlePortMessage:(NSPortMessage *)portMessage 186 { 187 InterThreadMessage *msg; 188 NSArray *components; 189 NSData *data; 190 191 components = [portMessage components]; 192 assert(1 == [components count]); 193 194 data = [components objectAtIndex:0]; 195 msg = *((InterThreadMessage **) [data bytes]); 196 197 switch (msg->type) 198 { 199 case kITMPostNotification: 200 [[NSNotificationCenter defaultCenter] 201 postNotification:msg->data.notification]; 202 [msg->data.notification release]; 203 break; 204 205 case kITMPerformSelector0Args: 206 [msg->data.sel.receiver performSelector:msg->data.sel.selector]; 207 [msg->data.sel.receiver release]; 208 break; 209 210 case kITMPerformSelector1Args: 211 [msg->data.sel.receiver performSelector:msg->data.sel.selector 212 withObject:msg->data.sel.arg1]; 213 [msg->data.sel.receiver release]; 214 [msg->data.sel.arg1 release]; 215 break; 216 217 case kITMPerformSelector2Args: 218 [msg->data.sel.receiver performSelector:msg->data.sel.selector 219 withObject:msg->data.sel.arg1 220 withObject:msg->data.sel.arg2]; 221 [msg->data.sel.receiver release]; 222 [msg->data.sel.arg1 release]; 223 [msg->data.sel.arg2 release]; 224 break; 225 226 default: 227 assert(0); 228 } 229 230 free(msg); 231 } 232 233 @end 234 235 236 237 238 239 static void 240 postMessage (InterThreadMessage *message, NSThread *thread, NSDate *limitDate) 241 { 242 NSPortMessage *portMessage; 243 NSMutableArray *components; 244 NSPort *port; 245 NSData *data; 246 BOOL retval; 247 248 if (nil == thread) { thread = [NSThread currentThread]; } 249 port = messagePortForThread(thread); 250 assert(nil != port); 251 252 data = [[NSData alloc] initWithBytes:&message length:sizeof(void *)]; 253 components = [[NSMutableArray alloc] initWithObjects:&data count:1]; 254 portMessage = [[NSPortMessage alloc] initWithSendPort:port 255 receivePort:nil 256 components:components]; 257 258 if (nil == limitDate) { limitDate = [NSDate distantFuture]; } 259 retval = [portMessage sendBeforeDate:limitDate]; 260 [portMessage release]; 261 [components release]; 262 [data release]; 263 264 if (!retval) { 265 [NSException raise:NSPortTimeoutException 266 format:@"Can't send message to thread %@: timeout " 267 @"before date %@", thread, limitDate]; 268 } 269 } 270 271 static void 272 performSelector (InterThreadMessageType type, SEL selector, id receiver, 273 id object1, id object2, NSThread *thread, NSDate *limitDate) 274 { 275 if( [thread isEqual:[NSThread currentThread]] ) { 276 [receiver performSelector:selector withObject:object1 withObject:object2]; 116 static void performSelector(SEL selector, id receiver, id object, NSThread *thread, BOOL wait) { 117 if( ! thread || [thread isEqual:[NSThread currentThread]] ) { 118 [receiver performSelector:selector withObject:object]; 277 119 return; 278 120 } 279 121 280 InterThreadMessage *msg; 281 282 assert(NULL != selector); 283 284 if (nil != receiver) { 285 msg = (InterThreadMessage *) malloc(sizeof(struct InterThreadMessage)); 286 bzero(msg, sizeof(struct InterThreadMessage)); 287 msg->type = type; 288 msg->data.sel.selector = selector; 289 msg->data.sel.receiver = [receiver retain]; 290 msg->data.sel.arg1 = [object1 retain]; 291 msg->data.sel.arg2 = [object2 retain]; 292 293 postMessage(msg, thread, limitDate); 294 } 295 } 296 297 static void 298 postNotification (NSNotification *notification, NSThread *thread, 299 NSDate *limitDate) 300 { 301 if( [thread isEqual:[NSThread currentThread]] ) { 302 [[NSNotificationCenter defaultCenter] postNotification:notification]; 122 if(useSystemThreadPerformSelector()) { 123 [receiver performSelector:selector onThread:thread withObject:object waitUntilDone:wait]; 303 124 return; 304 125 } 305 126 306 InterThreadMessage *msg; 127 InterThreadMessage *msg = (InterThreadMessage *)malloc(sizeof(struct InterThreadMessage)); 128 bzero(msg, sizeof(struct InterThreadMessage)); 307 129 308 assert(nil != notification); 309 310 msg = (InterThreadMessage *) malloc(sizeof(struct InterThreadMessage)); 311 bzero(msg, sizeof(struct InterThreadMessage)); 312 msg->type = kITMPostNotification; 313 msg->data.notification = [notification retain]; 130 msg->selector = selector; 131 msg->receiver = [receiver retain]; 132 msg->arg = [object retain]; 314 133 315 postMessage(msg, thread, limitDate); 134 NSPort *port = messagePortForThread(thread); 135 NSData *data = [[NSData alloc] initWithBytes:&msg length:sizeof(void *)]; 136 NSMutableArray *components = [[NSMutableArray alloc] initWithObjects:&data count:1]; 137 NSPortMessage *portMessage = [[NSPortMessage alloc] initWithSendPort:port receivePort:nil components:components]; 138 139 [portMessage sendBeforeDate:[NSDate distantFuture]]; 140 141 [portMessage release]; 142 [components release]; 143 [data release]; 316 144 } 317 145 318 319 320 321 322 323 146 @implementation NSObject (InterThreadMessaging) 324 325 - (void) performSelector:(SEL)selector 326 inThread:(NSThread *)thread 327 { 328 performSelector(kITMPerformSelector0Args, selector, self, nil, nil, 329 thread, nil); 147 - (void) performSelector:(SEL)selector inThread:(NSThread *)thread { 148 performSelector(selector, self, nil, thread, YES); 330 149 } 331 150 332 - (void) performSelector:(SEL)selector 333 inThread:(NSThread *)thread 334 beforeDate:(NSDate *)limitDate 335 { 336 performSelector(kITMPerformSelector0Args, selector, self, nil, nil, 337 thread, limitDate); 151 - (void) performSelector:(SEL)selector inThread:(NSThread *)thread waitUntilDone:(BOOL)wait { 152 performSelector(selector, self, nil, thread, wait); 338 153 } 339 154 340 - (void) performSelector:(SEL)selector 341 withObject:(id)object 342 inThread:(NSThread *)thread 343 { 344 performSelector(kITMPerformSelector1Args, selector, self, object, nil, 345 thread, nil); 155 - (void) performSelector:(SEL)selector withObject:(id)object inThread:(NSThread *)thread { 156 performSelector(selector, self, object, thread, YES); 346 157 } 347 158 348 - (void) performSelector:(SEL)selector 349 withObject:(id)object 350 inThread:(NSThread *)thread 351 beforeDate:(NSDate *)limitDate 352 { 353 performSelector(kITMPerformSelector1Args, selector, self, object, nil, 354 thread, limitDate); 159 - (void) performSelector:(SEL)selector withObject:(id)object inThread:(NSThread *)thread waitUntilDone:(BOOL)wait { 160 performSelector(selector, self, object, thread, wait); 355 161 } 356 357 - (void) performSelector:(SEL)selector358 withObject:(id)object1359 withObject:(id)object2360 inThread:(NSThread *)thread361 {362 performSelector(kITMPerformSelector2Args, selector, self, object1, object2,363 thread, nil);364 }365 366 - (void) performSelector:(SEL)selector367 withObject:(id)object1368 withObject:(id)object2369 inThread:(NSThread *)thread370 beforeDate:(NSDate *)limitDate371 {372 performSelector(kITMPerformSelector2Args, selector, self, object1, object2,373 thread, limitDate);374 }375 376 162 @end 377 378 379 380 @implementation NSNotificationCenter (InterThreadMessaging)381 382 - (void) postNotification:(NSNotification *)notification383 inThread:(NSThread *)thread384 {385 postNotification(notification, thread, nil);386 }387 388 - (void) postNotification:(NSNotification *)notification389 inThread:(NSThread *)thread390 beforeDate:(NSDate *)limitDate391 {392 postNotification(notification, thread, limitDate);393 }394 395 - (void) postNotificationName:(NSString *)name396 object:(id)object397 inThread:(NSThread *)thread398 {399 NSNotification *notification;400 401 notification = [NSNotification notificationWithName:name402 object:object403 userInfo:nil];404 postNotification(notification, thread, nil);405 }406 407 - (void) postNotificationName:(NSString *)name408 object:(id)object409 inThread:(NSThread *)thread410 beforeDate:(NSDate *)limitDate411 {412 NSNotification *notification;413 414 notification = [NSNotification notificationWithName:name415 object:object416 userInfo:nil];417 postNotification(notification, thread, limitDate);418 }419 420 - (void) postNotificationName:(NSString *)name421 object:(id)object422 userInfo:(NSDictionary *)userInfo423 inThread:(NSThread *)thread424 {425 NSNotification *notification;426 427 notification = [NSNotification notificationWithName:name428 object:object429 userInfo:userInfo];430 postNotification(notification, thread, nil);431 }432 433 - (void) postNotificationName:(NSString *)name434 object:(id)object435 userInfo:(NSDictionary *)userInfo436 inThread:(NSThread *)thread437 beforeDate:(NSDate *)limitDate438 {439 NSNotification *notification;440 441 notification = [NSNotification notificationWithName:name442 object:object443 userInfo:userInfo];444 postNotification(notification, thread, limitDate);445 }446 447 @end448 449 trunk/Chat Core/MVDirectClientConnection.h
r3539 r3713 1 #import "Transmission.h"2 3 1 @class AsyncSocket; 4 2 … … 10 8 AsyncSocket *_connection; 11 9 AsyncSocket *_acceptConnection; 12 tr_natpmp_t*_natpmp;13 tr_upnp_t*_upnp;10 void *_natpmp; 11 void *_upnp; 14 12 NSThread *_connectionThread; 15 13 NSConditionLock *_threadWaitLock; trunk/Chat Core/MVDirectClientConnection.m
r3574 r3713 6 6 #import "MVFileTransfer.h" 7 7 #import "MVUtilities.h" 8 #import "Transmission.h" 8 9 9 10 #import <arpa/inet.h> … … 105 106 if( ! _connectionThread ) return; 106 107 107 [self performSelector:@selector( _connectToHost:onPort: ) withObject:host withObject:[NSNumber numberWithUnsignedShort:port] inThread:_connectionThread]; 108 NSDictionary *info = [[NSDictionary allocWithZone:NULL] initWithObjectsAndKeys:[NSNumber numberWithUnsignedShort:port], @"port", host, @"host", nil]; 109 [self performSelector:@selector( _connect: ) withObject:info inThread:_connectionThread]; 110 [info release]; 108 111 } 109 112 … … 232 235 } 233 236 234 - (void) _connect ToHost:(NSString *) host onPort:(NSNumber *) port{237 - (void) _connect:(NSDictionary *) info { 235 238 MVAssertCorrectThreadRequired( _connectionThread ); 236 239 … … 238 241 239 242 _connection = [[AsyncSocket allocWithZone:nil] initWithDelegate:self]; 243 244 NSString *host = [info objectForKey:@"host"]; 245 NSNumber *port = [info objectForKey:@"port"]; 240 246 241 247 if( ! [_connection connectToHost:host onPort:[port unsignedShortValue] error:NULL] ) { … … 338 344 pool = nil; 339 345 340 BOOL active = YES; 341 while( active && ! _done ) { 346 while( ! _done ) { 342 347 if( _upnp ) tr_upnpPulse( _upnp ); 343 348 if( _natpmp ) tr_natpmpPulse( _natpmp ); … … 346 351 347 352 NSDate *timeout = [[NSDate allocWithZone:nil] initWithTimeIntervalSinceNow:5.]; 348 active =[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout];353 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; 349 354 [timeout release]; 350 355
