Changeset 3713

Show
Ignore:
Timestamp:
08/15/07 10:58:11 (1 year ago)
Author:
timothy
Message:

Rework InterThreadMessaging? to use new methods in Foundation if they exist.

Files:

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  -*-*/ 
    21/* 
    32 * InterThreadMessaging -- InterThreadMessaging.h 
    43 * Created by toby on Tue Jun 19 2001. 
    5  * 
    6  * A low-cost-but-not-quite-as-general alternative to D.O. 
    7  * 
    84 */ 
    95 
    10 #import <Foundation/Foundation.h> 
    11  
    12  
    136@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; 
    288@end 
    299 
    30  
    31  
    32 /* Invoke in the specified thread a method on an object.  The target 
    33    thread must have been readied for inter-thread messages by invoking 
    34    +prepareForInterThreadMessages.  It must be running its run loop in 
    35    order to receive the messages. 
    36  
    37    In some situations, a sender may be able to blast messages to an object 
    38    faster than they can be processed in the target thread.  To prevent things 
    39    from spiraling out of control, the underlying NSPorts implement a throtling 
    40    mechanism in the form of a fixed queue size.  When this queue is filled, all 
    41    further messages are rejected until until a message has been pulled off the 
    42    queue.  The sender may specify a limit date; if the queue is full, the 
    43    sender will block until this limit date expires or until space is made in 
    44    the queue.  An NSPortTimeoutException exception is thrown if the limit date 
    45    expires (or if no limit date is specified) before the message can be 
    46    delivered. 
    47  
    48    There is one very important point to watch out for: to prevent heinously 
    49    difficult to debug memory smashers, the receing object and all of its 
    50    arguments are retained in the context of the sending thread.  When the 
    51    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 for 
    53    the objects to be deallocated in a thread different from the one they were 
    54    allocated in.  (In general, you don't need to worry about simple/immutable 
    55    objects, such as NSString, NSData, etc.) */ 
    56  
    5710@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; 
    8615@end 
    87  
    88  
    89  
    90  
    91 /* Post a notification in the specified thread.  The target thread must 
    92    have been readied for inter-thread messages by sending itself the 
    93    +prepareForInterThreadMessages.  It must be running its run loop in 
    94    order to receive the messages. 
    95  
    96    In some situations, a sender may be able to blast messages to an object 
    97    faster than they can be processed in the target thread.  To prevent things 
    98    from spiraling out of control, the underlying NSPorts implement a throtling 
    99    mechanism in the form of a fixed queue size.  When this queue is filled, all 
    100    further messages are rejected until until a message has been pulled off the 
    101    queue.  The sender may specify a limit date; if the queue is full, the 
    102    sender will block until this limit date expires or until space is made in 
    103    the queue.  An NSPortTimeoutException exception is thrown if the limit date 
    104    expires (or if no limit date is specified) before the message can be 
    105    delivered. 
    106  
    107    There is one very important point to watch out for: to prevent heinously 
    108    difficult to debug memory smashers, the notification object (and 
    109    consequently the userInfo dictionary) are retained in the context of 
    110    the sending thread.  When the message has been delivered in the target 
    111    thread, the notification object is auto-released IN THE CONTEXT OF THE 
    112    TARGET THREAD.  Thus, it is possible for objects to be deallocated in a 
    113    thread different from the one they were allocated in.  (In general, you 
    114    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 *)notification 
    120          inThread:(NSThread *)thread;   // before date [NSDate distantFuture] 
    121  
    122 - (void) postNotification:(NSNotification *)notification 
    123          inThread:(NSThread *)thread 
    124          beforeDate:(NSDate *)limitDate; 
    125  
    126 - (void) postNotificationName:(NSString *)name 
    127          object:(id)object 
    128          inThread:(NSThread *)thread;   // before date [NSDate distantFuture] 
    129  
    130 - (void) postNotificationName:(NSString *)name 
    131          object:(id)object 
    132          inThread:(NSThread *)thread 
    133          beforeDate:(NSDate *)limitDate; 
    134  
    135 - (void) postNotificationName:(NSString *)name 
    136          object:(id)object 
    137          userInfo:(NSDictionary *)userInfo 
    138          inThread:(NSThread *)thread;   // before date [NSDate distantFuture] 
    139  
    140 - (void) postNotificationName:(NSString *)name 
    141          object:(id)object 
    142          userInfo:(NSDictionary *)userInfo 
    143          inThread:(NSThread *)thread 
    144          beforeDate:(NSDate *)limitDate; 
    145  
    146 @end 
    147  
  • trunk/Chat Core/InterThreadMessaging.m

    r3710 r3713  
    1 /*-*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4  -*-*/ 
    21/* 
    32 * InterThreadMessaging -- InterThreadMessaging.m 
    43 * Created by toby on Tue Jun 19 2001. 
    5  * 
    64 */ 
    75 
    8 #import <pthread.h> 
    96#import "InterThreadMessaging.h" 
    107 
     8@interface NSObject (LeopardOnly) 
     9- (void) performSelector:(SEL) selector onThread:(NSThread *) thread withObject:(id) object waitUntilDone:(BOOL) wait; 
     10@end 
    1111 
    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.) */ 
     12static BOOL useSystemThreadPerformSelector() { 
     13        static BOOL useSystemVersion = NO; 
     14        static BOOL checkedSystem = NO; 
    2015 
    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        } 
    2920 
     21        return useSystemVersion; 
     22} 
    3023 
    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> 
    3625 
    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. */ 
     26typedef struct InterThreadMessage { 
     27        SEL selector; 
     28        id receiver; 
     29        id arg; 
     30} InterThreadMessage; 
    5631 
    5732static NSMapTable *pThreadMessagePorts = NULL; 
    58 static NSMapTable *pThreadRunLoops = NULL; 
    5933static pthread_mutex_t pGate; 
    6034 
     
    6438@end 
    6539 
    66 static void 
    67 createMessagePortForThread (NSThread *thread, NSRunLoop *runLoop) 
    68 
    69     NSPort *port; 
     40static void createMessagePortForThread(NSThread *thread, NSRunLoop *runLoop) { 
     41        pthread_mutex_lock(&pGate); 
    7042 
    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]; 
    7548 
    76     pthread_mutex_lock(&pGate); 
     49                NSMapInsertKnownAbsent(pThreadMessagePorts, thread, port); 
     50                [port release]; 
     51        } 
    7752 
    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); 
    9154} 
    9255 
    93 static NSPort * 
    94 messagePortForThread (NSThread *thread) 
    95 
    96     NSPort *port
     56static NSPort *messagePortForThread(NSThread *thread) { 
     57        pthread_mutex_lock(&pGate); 
     58        NSPort *port = NSMapGet(pThreadMessagePorts, thread); 
     59       pthread_mutex_unlock(&pGate)
    9760 
    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]; 
    10062 
    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; 
    11364} 
    11465 
    115 static void 
    116 removeMessagePortForThread (NSThread *thread) 
    117 
    118     NSPort *port; 
     66static void removeMessagePortForThread(NSThread *thread) { 
     67        pthread_mutex_lock(&pGate); 
    11968 
    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        } 
    12274 
    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); 
    13476} 
    13577 
     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 
    13686 
    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        } 
    14896} 
    14997 
     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} 
    150114@end 
    151115 
    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]; 
     116static 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]; 
    277119                return; 
    278120        } 
    279121 
    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]; 
    303124                return; 
    304125        } 
    305126 
    306     InterThreadMessage *msg; 
     127        InterThreadMessage *msg = (InterThreadMessage *)malloc(sizeof(struct InterThreadMessage)); 
     128        bzero(msg, sizeof(struct InterThreadMessage)); 
    307129 
    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]; 
    314133 
    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]; 
    316144} 
    317145 
    318  
    319  
    320  
    321  
    322  
    323146@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); 
    330149} 
    331150 
    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); 
    338153} 
    339154 
    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); 
    346157} 
    347158 
    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); 
    355161} 
    356  
    357 - (void) performSelector:(SEL)selector 
    358          withObject:(id)object1 
    359          withObject:(id)object2 
    360          inThread:(NSThread *)thread 
    361 { 
    362     performSelector(kITMPerformSelector2Args, selector, self, object1, object2, 
    363                     thread, nil); 
    364 } 
    365  
    366 - (void) performSelector:(SEL)selector 
    367          withObject:(id)object1 
    368          withObject:(id)object2 
    369          inThread:(NSThread *)thread 
    370          beforeDate:(NSDate *)limitDate 
    371 { 
    372     performSelector(kITMPerformSelector2Args, selector, self, object1, object2, 
    373                     thread, limitDate); 
    374 } 
    375  
    376162@end 
    377  
    378  
    379  
    380 @implementation NSNotificationCenter (InterThreadMessaging) 
    381  
    382 - (void) postNotification:(NSNotification *)notification 
    383          inThread:(NSThread *)thread 
    384 { 
    385     postNotification(notification, thread, nil); 
    386 } 
    387  
    388 - (void) postNotification:(NSNotification *)notification 
    389          inThread:(NSThread *)thread 
    390          beforeDate:(NSDate *)limitDate 
    391 { 
    392     postNotification(notification, thread, limitDate); 
    393 } 
    394  
    395 - (void) postNotificationName:(NSString *)name 
    396          object:(id)object 
    397          inThread:(NSThread *)thread 
    398 { 
    399     NSNotification *notification; 
    400      
    401     notification = [NSNotification notificationWithName:name 
    402                                    object:object 
    403                                    userInfo:nil]; 
    404     postNotification(notification, thread, nil); 
    405 } 
    406  
    407 - (void) postNotificationName:(NSString *)name 
    408          object:(id)object 
    409          inThread:(NSThread *)thread 
    410          beforeDate:(NSDate *)limitDate 
    411 { 
    412     NSNotification *notification; 
    413      
    414     notification = [NSNotification notificationWithName:name 
    415                                    object:object 
    416                                    userInfo:nil]; 
    417     postNotification(notification, thread, limitDate); 
    418 } 
    419  
    420 - (void) postNotificationName:(NSString *)name 
    421          object:(id)object 
    422          userInfo:(NSDictionary *)userInfo 
    423          inThread:(NSThread *)thread 
    424 { 
    425     NSNotification *notification; 
    426      
    427     notification = [NSNotification notificationWithName:name 
    428                                    object:object 
    429                                    userInfo:userInfo]; 
    430     postNotification(notification, thread, nil); 
    431 } 
    432  
    433 - (void) postNotificationName:(NSString *)name 
    434          object:(id)object 
    435          userInfo:(NSDictionary *)userInfo 
    436          inThread:(NSThread *)thread 
    437          beforeDate:(NSDate *)limitDate 
    438 { 
    439     NSNotification *notification; 
    440      
    441     notification = [NSNotification notificationWithName:name 
    442                                    object:object 
    443                                    userInfo:userInfo]; 
    444     postNotification(notification, thread, limitDate); 
    445 } 
    446  
    447 @end 
    448  
    449  
  • trunk/Chat Core/MVDirectClientConnection.h

    r3539 r3713  
    1 #import "Transmission.h" 
    2  
    31@class AsyncSocket; 
    42 
     
    108        AsyncSocket *_connection; 
    119        AsyncSocket *_acceptConnection; 
    12         tr_natpmp_t *_natpmp; 
    13         tr_upnp_t *_upnp; 
     10        void *_natpmp; 
     11        void *_upnp; 
    1412        NSThread *_connectionThread; 
    1513        NSConditionLock *_threadWaitLock; 
  • trunk/Chat Core/MVDirectClientConnection.m

    r3574 r3713  
    66#import "MVFileTransfer.h" 
    77#import "MVUtilities.h" 
     8#import "Transmission.h" 
    89 
    910#import <arpa/inet.h> 
     
    105106        if( ! _connectionThread ) return; 
    106107 
    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]; 
    108111} 
    109112 
     
    232235} 
    233236 
    234 - (void) _connectToHost:(NSString *) host onPort:(NSNumber *) port
     237- (void) _connect:(NSDictionary *) info
    235238        MVAssertCorrectThreadRequired( _connectionThread ); 
    236239 
     
    238241 
    239242        _connection = [[AsyncSocket allocWithZone:nil] initWithDelegate:self]; 
     243 
     244        NSString *host = [info objectForKey:@"host"]; 
     245        NSNumber *port = [info objectForKey:@"port"]; 
    240246 
    241247        if( ! [_connection connectToHost:host onPort:[port unsignedShortValue] error:NULL] ) { 
     
    338344        pool = nil; 
    339345 
    340         BOOL active = YES; 
    341         while( active && ! _done ) { 
     346        while( ! _done ) { 
    342347                if( _upnp ) tr_upnpPulse( _upnp ); 
    343348                if( _natpmp ) tr_natpmpPulse( _natpmp ); 
     
    346351 
    347352                NSDate *timeout = [[NSDate allocWithZone:nil] initWithTimeIntervalSinceNow:5.]; 
    348                 active = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; 
     353                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; 
    349354                [timeout release]; 
    350355