26
26
Boston, MA 02111 USA.
28
28
<title>NSConnection class reference</title>
29
$Date: 2011-06-18 18:46:28 +0100 (Sat, 18 Jun 2011) $ $Revision: 33340 $
29
$Date: 2012-01-30 04:31:40 -0700 (Mon, 30 Jan 2012) $ $Revision: 34665 $
34
#if !defined (__GNU_LIBOBJC__)
35
# include <objc/encoding.h>
34
38
#define GS_NSConnection_IVARS \
36
40
BOOL _independentQueueing; \
174
178
- (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target;
177
#define F_LOCK(X) {NSDebugFLLog(@"GSConnection",@"Lock %@",X);[X lock];}
178
#define F_UNLOCK(X) {NSDebugFLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
179
#define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
180
#define M_UNLOCK(X) {NSDebugMLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
181
#define GS_F_LOCK(X) \
182
{NSDebugFLLog(@"GSConnection",@"Lock %@",X);[X lock];}
183
#define GS_F_UNLOCK(X) \
184
{NSDebugFLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
185
#define GS_M_LOCK(X) \
186
{NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
187
#define GSM_UNLOCK(X) \
188
{NSDebugMLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
182
190
NSString * const NSDestinationInvalidException =
183
191
@"NSDestinationInvalidException";
361
369
static int debug_connection = 0;
363
371
static NSHashTable *connection_table;
364
static NSLock *connection_table_gate = nil;
372
static GSLazyRecursiveLock *connection_table_gate = nil;
367
375
* Locate an existing connection with the specified send and receive ports.
373
381
NSHashEnumerator enumerator;
376
F_LOCK(connection_table_gate);
384
GS_F_LOCK(connection_table_gate);
377
385
enumerator = NSEnumerateHashTable(connection_table);
378
386
while ((c = (NSConnection*)NSNextHashEnumeratorItem(&enumerator)) != nil)
404
F_LOCK(root_object_map_gate);
412
GS_F_LOCK(root_object_map_gate);
405
413
rootObject = (id)NSMapGet(root_object_map, (void*)(uintptr_t)aPort);
406
F_UNLOCK(root_object_map_gate);
414
GS_F_UNLOCK(root_object_map_gate);
407
415
return rootObject;
414
422
id oldRootObject;
416
F_LOCK(root_object_map_gate);
424
GS_F_LOCK(root_object_map_gate);
417
425
oldRootObject = (id)NSMapGet(root_object_map, (void*)(uintptr_t)aPort);
418
426
if (oldRootObject != anObj)
427
435
NSMapRemove(root_object_map, (void*)(uintptr_t)aPort);
430
F_UNLOCK(root_object_map_gate);
438
GS_F_UNLOCK(root_object_map_gate);
433
441
static NSMapTable *targetToCached = NULL;
456
M_LOCK(connection_table_gate);
464
GS_M_LOCK(connection_table_gate);
457
465
a = NSAllHashTableObjects(connection_table);
458
M_UNLOCK(connection_table_gate);
466
GSM_UNLOCK(connection_table_gate);
658
666
NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
661
NSCreateMapTable(NSIntMapKeyCallBacks,
669
NSCreateMapTable(NSIntegerMapKeyCallBacks,
662
670
NSObjectMapValueCallBacks, 0);
664
672
root_object_map =
1034
1042
@"Send: %@\n Recv: %@", parent, self, s, r);
1037
M_LOCK(connection_table_gate);
1045
GS_M_LOCK(connection_table_gate);
1039
1047
IisValid = YES;
1040
1048
IreceivePort = RETAIN(r);
1219
1227
implementation of [-release] to automatically remove the connection
1220
1228
from this array when it is the only thing retaining it. */
1221
1229
NSHashInsert(connection_table, (void*)self);
1222
M_UNLOCK(connection_table_gate);
1230
GSM_UNLOCK(connection_table_gate);
1224
1232
[nCenter postNotificationName: NSConnectionDidInitializeNotification
1254
1262
//[self _shutdown];
1257
M_LOCK(connection_table_gate);
1265
GS_M_LOCK(connection_table_gate);
1258
1266
NSHashRemove(connection_table, self);
1259
M_UNLOCK(connection_table_gate);
1267
GSM_UNLOCK(connection_table_gate);
1269
GSM_UNLOCK(IrefGate);
1264
1272
* Don't need notifications any more - so remove self as observer.
1498
1506
* it from the table so that no other thread will find it
1499
1507
* and try to use it while it is being deallocated.
1501
M_LOCK(connection_table_gate);
1509
GS_M_LOCK(connection_table_gate);
1502
1510
if (NSDecrementExtraRefCountWasZero(self))
1504
1512
NSHashRemove(connection_table, self);
1505
M_UNLOCK(connection_table_gate);
1513
GSM_UNLOCK(connection_table_gate);
1506
1514
[self dealloc];
1510
M_UNLOCK(connection_table_gate);
1518
GSM_UNLOCK(connection_table_gate);
2043
2051
* the IreplyMap. However, in case the other end has already sent us
2044
2052
* a response, we must check for it and scrap it if necessary.
2054
GS_M_LOCK(IrefGate);
2047
2055
node = GSIMapNodeForKey(IreplyMap, (GSIMapKey)(NSUInteger)seq);
2048
2056
if (node != 0 && node->value.obj != dummyObject)
2208
2220
unsigned result;
2210
M_LOCK(connection_table_gate);
2222
GS_M_LOCK(connection_table_gate);
2211
2223
result = NSCountHashTable(connection_table);
2212
M_UNLOCK(connection_table_gate);
2224
GSM_UNLOCK(connection_table_gate);
2219
2231
NSHashEnumerator enumerator;
2220
2232
NSConnection *o;
2222
M_LOCK(connection_table_gate);
2234
GS_M_LOCK(connection_table_gate);
2223
2235
enumerator = NSEnumerateHashTable(connection_table);
2224
2236
while ((o = (NSConnection*)NSNextHashEnumeratorItem(&enumerator)) != nil)
2322
2334
* If REPLY_DEPTH is non-zero, we may still want to service it now
2323
2335
* if independent_queuing is NO.
2325
M_LOCK(GSIVar(conn, _refGate));
2337
GS_M_LOCK(GSIVar(conn, _refGate));
2326
2338
if (GSIVar(conn, _requestDepth) == 0
2327
2339
|| GSIVar(conn, _independentQueueing) == NO)
2329
2341
GSIVar(conn, _requestDepth)++;
2330
M_UNLOCK(GSIVar(conn, _refGate));
2342
GSM_UNLOCK(GSIVar(conn, _refGate));
2331
2343
[conn _service_forwardForProxy: rmc]; // Catches exceptions
2332
M_LOCK(GSIVar(conn, _refGate));
2344
GS_M_LOCK(GSIVar(conn, _refGate));
2333
2345
GSIVar(conn, _requestDepth)--;
2346
2358
rmc = [GSIVar(conn, _requestQueue) objectAtIndex: 0];
2347
2359
[GSIVar(conn, _requestQueue) removeObjectAtIndex: 0];
2348
M_UNLOCK(GSIVar(conn, _refGate));
2360
GSM_UNLOCK(GSIVar(conn, _refGate));
2349
2361
[conn _service_forwardForProxy: rmc]; // Catches exceptions
2350
M_LOCK(GSIVar(conn, _refGate));
2362
GS_M_LOCK(GSIVar(conn, _refGate));
2352
M_UNLOCK(GSIVar(conn, _refGate));
2364
GSM_UNLOCK(GSIVar(conn, _refGate));
2375
2387
[self _doneInRmc: rmc];
2378
M_LOCK(GSIVar(conn, _refGate));
2390
GS_M_LOCK(GSIVar(conn, _refGate));
2379
2391
node = GSIMapNodeForKey(GSIVar(conn, _replyMap),
2380
2392
(GSIMapKey)(NSUInteger)sequence);
2549
2560
decoder = aRmc;
2551
/* Decode the object, (which is always the first argument to a method). */
2552
[decoder decodeValueOfObjCType: @encode(id) at: &object];
2562
/* Decode the object, (which is always the first argument to a method).
2563
* Use the -decodeObject method to ensure that the target of the
2564
* invocation is autoreleased and will be deallocated when we finish.
2566
object = [decoder decodeObject];
2554
2568
/* Decode the selector, (which is the second argument to a method). */
2555
2569
/* xxx @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */
2563
2577
as the ENCODED_TYPES string, but it will have different register
2564
2578
and stack locations if the ENCODED_TYPES came from a machine of a
2565
2579
different architecture. */
2566
if (GSObjCIsClass(object))
2568
meth = GSGetMethod(object, selector, NO, YES);
2570
else if (GSObjCIsInstance(object))
2572
meth = GSGetMethod(object_getClass(object), selector, YES, YES);
2580
sig = [object methodSignatureForSelector: selector];
2576
2583
[NSException raise: NSInvalidArgumentException
2577
format: @"decoded object %p is invalid", object];
2584
format: @"decoded object %p doesn't handle %s",
2585
object, sel_getName(selector)];
2587
type = [sig methodType];
2582
type = method_getTypeEncoding(meth);
2586
NSDebugLog(@"Local object <%p %s> doesn't implement: %s directly. "
2587
@"Will search for arbitrary signature.",
2589
class_getName(GSObjCIsClass(object)
2590
? object : (id)object_getClass(object)),
2591
sel_getName(selector));
2592
type = GSTypesFromSelector(selector);
2595
2589
/* Make sure we successfully got the method type, and that its
2596
2590
types match the ENCODED_TYPES. */
2597
2591
NSCParameterAssert (type);
2602
2596
encoded_types, type, sel_getName(selector)];
2605
sig = [NSMethodSignature signatureWithObjCTypes: type];
2606
2599
inv = [[NSInvocation alloc] initWithMethodSignature: sig];
2608
2601
tmptype = skip_argspec (type);
2926
2919
if (debug_connection > 3)
2927
2920
NSLog(@"releasing object with target (0x%x) on (%@) counter %d",
2928
2921
target, self, prox->_counter);
2922
GS_M_LOCK(IrefGate);
2932
2925
if (--(prox->_counter) == 0)
3132
3125
if (debug_connection > 5)
3133
3126
NSLog(@"Waiting for reply sequence %d on %@",
3135
M_LOCK(IrefGate); isLocked = YES;
3128
GS_M_LOCK(IrefGate); isLocked = YES;
3136
3129
while (IisValid == YES
3137
3130
&& (node = GSIMapNodeForKey(IreplyMap, (GSIMapKey)(NSUInteger)sn)) != 0
3138
3131
&& node->value.obj == dummyObject)
3140
3133
NSDate *limit_date;
3142
M_UNLOCK(IrefGate); isLocked = NO;
3135
GSM_UNLOCK(IrefGate); isLocked = NO;
3143
3136
if (start_date == nil)
3145
3138
start_date = [dateClass allocWithZone: NSDefaultMallocZone()];
3183
3176
&& (limit_date == timeout_date))
3184
3177
|| [timeout_date timeIntervalSinceNow] <= 0.0)
3186
M_LOCK(IrefGate); isLocked = YES;
3179
GS_M_LOCK(IrefGate); isLocked = YES;
3187
3180
node = GSIMapNodeForKey(IreplyMap, (GSIMapKey)(NSUInteger)sn);
3204
3197
rmc = node->value.obj;
3205
3198
GSIMapRemoveKey(IreplyMap, (GSIMapKey)(NSUInteger)sn);
3207
M_UNLOCK(IrefGate); isLocked = NO;
3200
GSM_UNLOCK(IrefGate); isLocked = NO;
3208
3201
TEST_RELEASE(start_date);
3209
3202
TEST_RELEASE(delay_date);
3210
3203
TEST_RELEASE(timeout_date);
3521
3514
(GSIMapKey)(NSUInteger)target, (GSIMapVal)((id)anObj));
3523
3516
if (debug_connection > 2)
3524
NSLog(@"add local object (0x%x) target (0x%x) "
3525
@"to connection (%@)", (uintptr_t)object, target, self);
3517
NSLog(@"add local object (%p) target (0x%x) "
3518
@"to connection (%@)", object, target, self);
3520
GSM_UNLOCK(IrefGate);
3530
3523
- (NSDistantObject*) retainOrAddLocal: (NSDistantObject*)proxy
3597
3590
item = [CachedLocalObject newWithObject: prox time: 5];
3598
3591
NSMapInsert(targetToCached, (void*)(uintptr_t)target, item);
3599
M_UNLOCK(cached_proxies_gate);
3592
GSM_UNLOCK(cached_proxies_gate);
3601
3594
if (debug_connection > 3)
3602
NSLog(@"placed local object (0x%x) target (0x%x) in cache",
3603
(uintptr_t)anObj, target);
3595
NSLog(@"placed local object (%p) target (0x%x) in cache",
3615
3608
GSIMapRemoveKey(IlocalTargets, (GSIMapKey)(NSUInteger)target);
3617
3610
if (debug_connection > 2)
3618
NSLog(@"removed local object (0x%x) target (0x%x) "
3619
@"from connection (%@) (ref %d)", (uintptr_t)anObj, target, self, val);
3611
NSLog(@"removed local object (%p) target (0x%x) "
3612
@"from connection (%@) (ref %d)", anObj, target, self, val);
3614
GSM_UNLOCK(IrefGate);
3624
3617
- (void) _release_target: (unsigned)target count: (unsigned)number
3686
3679
CachedLocalObject *cached;
3688
M_LOCK(cached_proxies_gate);
3681
GS_M_LOCK(cached_proxies_gate);
3689
3682
cached = NSMapGet (targetToCached, (void*)(uintptr_t)target);
3690
3683
if (cached != nil)
3700
3693
if (debug_connection > 3)
3701
3694
NSLog(@"target (0x%x) moved from cache", target);
3703
M_UNLOCK(cached_proxies_gate);
3696
GSM_UNLOCK(cached_proxies_gate);
3712
3705
NSHashEnumerator enumerator;
3713
3706
NSConnection *c;
3715
M_LOCK(connection_table_gate);
3708
GS_M_LOCK(connection_table_gate);
3716
3709
enumerator = NSEnumerateHashTable(connection_table);
3717
3710
while (proxy == nil
3718
3711
&& (c = (NSConnection*)NSNextHashEnumeratorItem(&enumerator)) != nil)
3720
3713
if (c != self && [c isValid] == YES)
3722
M_LOCK(GSIVar(c, _refGate));
3715
GS_M_LOCK(GSIVar(c, _refGate));
3723
3716
node = GSIMapNodeForKey(GSIVar(c, _localTargets),
3724
3717
(GSIMapKey)(NSUInteger)target);
3749
3742
GSIMapAddPair(IlocalTargets,
3750
3743
(GSIMapKey)(NSUInteger)target, (GSIMapVal)((id)proxy));
3752
M_UNLOCK(GSIVar(c, _refGate));
3745
GSM_UNLOCK(GSIVar(c, _refGate));
3755
3748
NSEndHashTableEnumeration(&enumerator);
3756
M_UNLOCK(connection_table_gate);
3749
GSM_UNLOCK(connection_table_gate);
3752
GSM_UNLOCK(IrefGate);
3761
3754
if (proxy == nil)
4012
4005
NSEnumerator *enumerator;
4013
4006
NSConnection *c;
4015
M_LOCK (connection_table_gate);
4008
GS_M_LOCK (connection_table_gate);
4016
4009
enumerator = [NSAllHashTableObjects(connection_table) objectEnumerator];
4017
M_UNLOCK (connection_table_gate);
4010
GSM_UNLOCK (connection_table_gate);
4020
4013
* We enumerate an array copy of the contents of the hash table