From b5cd1a215be0345d3c5da476fd27743a86fd4d40 Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 5 Jul 2000 12:23:00 +0000 Subject: [PATCH] DO tidyups git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6875 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 10 + Headers/gnustep/base/NSConnection.h | 14 +- Source/NSConnection.m | 504 ++++++++++++++++++++-------- Source/NSDistantObject.m | 50 +-- Source/NSPortNameServer.m | 40 ++- 5 files changed, 431 insertions(+), 187 deletions(-) diff --git a/ChangeLog b/ChangeLog index 119614c35..baf048bbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2000-07-05 Richard Frith-Macdonald + + * Source/NSConnection.m: Update to use GSIMap rather than NSMap in + order to regain performance lost by adding code to ensure that reply + packets cannot be leaked. Fixed error in old connection code - due + to a typing error a line had got deleted that was removing the + connection from the global table on deallocation. + * Source/NSPortNameServer.m: Fix to avoid errors when given bad + nameserver IP address info. + 2000-07-04 Richard Frith-Macdonald * Makefile.preamble: define GS_NEW_DO to specify whether the diff --git a/Headers/gnustep/base/NSConnection.h b/Headers/gnustep/base/NSConnection.h index 984a33e86..479feb45e 100644 --- a/Headers/gnustep/base/NSConnection.h +++ b/Headers/gnustep/base/NSConnection.h @@ -73,10 +73,16 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */ unsigned _reqInCount; unsigned _repOutCount; unsigned _repInCount; - NSMapTable *_localObjects; - NSMapTable *_localTargets; - NSMapTable *_remoteProxies; - NSMapTable *_replyMap; +#ifndef _IN_CONNECTION_M +#define GSIMapTable void* +#endif + GSIMapTable _localObjects; + GSIMapTable _localTargets; + GSIMapTable _remoteProxies; + GSIMapTable _replyMap; +#ifndef _IN_CONNECTION_M +#undef GSIMapTable +#endif NSTimeInterval _replyTimeout; NSTimeInterval _requestTimeout; NSMutableArray *_requestModes; diff --git a/Source/NSConnection.m b/Source/NSConnection.m index aed1d685f..6c6736485 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -30,7 +30,22 @@ #include #include +/* + * Setup for inline operation of pointer map tables. + */ +#define GSI_MAP_RETAIN_KEY(X) +#define GSI_MAP_RELEASE_KEY(X) +#define GSI_MAP_RETAIN_VAL(X) +#define GSI_MAP_RELEASE_VAL(X) +#define GSI_MAP_HASH(X) ((X).uint ^ ((X).uint >> 3)) +#define GSI_MAP_EQUAL(X,Y) ((X).ptr == (Y).ptr) + +#include + +#define _IN_CONNECTION_M #include +#undef _IN_CONNECTION_M + #include #include @@ -57,6 +72,7 @@ #define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];} #define M_UNLOCK(X) {NSDebugMLLog(@"GSConnection",@"Unlock %@",X);[X unlock];} +static id dummyObject; static Class connectionClass; static Class dateClass; static Class distantObjectClass; @@ -166,7 +182,7 @@ static unsigned local_object_counter = 0; id obj; int time; } -- (BOOL)countdown; +- (BOOL) countdown; - (id) obj; + (id) newWithObject: (id)o time: (int)t; @end @@ -213,8 +229,7 @@ static unsigned local_object_counter = 0; - (void) _doneInRmc: (NSPortCoder*)c; - (NSPortCoder*) _getReplyRmc: (int)sn; - (NSPortCoder*) _makeInRmc: (NSMutableArray*)components; -- (NSPortCoder*) _makeOutRmc: (int)sequence; -- (int) _newMsgNumber; +- (NSPortCoder*) _makeOutRmc: (int)sequence generate: (int*)sno reply: (BOOL)f; - (void) _sendOutRmc: (NSPortCoder*)c type: (int)msgid; - (void) _service_forwardForProxy: (NSPortCoder*)rmc; @@ -227,7 +242,6 @@ static unsigned local_object_counter = 0; #define _proxiesGate _refGate #define _queueGate _refGate -#define sequenceNumberGate _refGate /* class defaults */ @@ -307,7 +321,7 @@ setRootObjectForInPort(id anObj, NSPort *aPort) static NSMapTable *all_connections_local_objects = NULL; static NSMapTable *all_connections_local_targets = NULL; static NSMapTable *all_connections_local_cached = NULL; -static NSLock *global_proxies_gate; +static NSLock *global_proxies_gate; @@ -427,6 +441,8 @@ static NSLock *global_proxies_gate; portCoderClass = [NSPortCoder class]; runLoopClass = [NSRunLoop class]; + dummyObject = [NSObject new]; + connection_table = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0); connection_table_gate = [NSLock new]; @@ -595,6 +611,7 @@ static NSLock *global_proxies_gate; NSConnection *conn; NSRunLoop *loop; id del; + NSZone *z = NSDefaultMallocZone(); /* * If the receive port is nil, deallocate connection and return nil. @@ -675,32 +692,28 @@ static NSLock *global_proxies_gate; * This maps request sequence numbers to the NSPortCoder objects representing * replies arriving from the remote connection. */ - _replyMap = - NSCreateMapTable(NSIntMapKeyCallBacks, - NSObjectMapValueCallBacks, 0); + _replyMap = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t)); + GSIMapInitWithZoneAndCapacity(_replyMap, z, 4); /* * This maps (void*)obj to (id)obj. The obj's are retained. * We use this instead of an NSHashTable because we only care about * the object's address, and don't want to send the -hash message to it. */ - _localObjects = - NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, - NSObjectMapValueCallBacks, 0); + _localObjects = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t)); + GSIMapInitWithZoneAndCapacity(_localObjects, z, 4); /* * This maps handles for local objects to their local proxies. */ - _localTargets = - NSCreateMapTable(NSIntMapKeyCallBacks, - NSNonOwnedPointerMapValueCallBacks, 0); + _localTargets = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t)); + GSIMapInitWithZoneAndCapacity(_localTargets, z, 4); /* * This maps [proxy targetForProxy] to proxy. The proxy's are retained. */ - _remoteProxies = - NSCreateMapTable(NSIntMapKeyCallBacks, - NSNonOwnedPointerMapValueCallBacks, 0); + _remoteProxies = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t)); + GSIMapInitWithZoneAndCapacity(_remoteProxies, z, 4); _requestDepth = 0; _delegate = nil; @@ -867,12 +880,17 @@ static NSLock *global_proxies_gate; M_LOCK(_proxiesGate); if (_localTargets != 0) { - NSArray *targets; - unsigned i; + NSMutableArray *targets; + unsigned i = _localTargets->nodeCount; + GSIMapNode node; - targets = NSAllMapTableValues(_localTargets); - IF_NO_GC(RETAIN(targets)); - i = [targets count]; + targets = [[NSMutableArray alloc] initWithCapacity: i]; + node = _localTargets->firstNode; + while (node != 0) + { + [targets addObject: node->value.obj]; + node = node->nextInMap; + } while (i-- > 0) { id t = [[targets objectAtIndex: i] localForProxy]; @@ -880,17 +898,27 @@ static NSLock *global_proxies_gate; [self removeLocalObject: t]; } RELEASE(targets); - NSFreeMapTable(_localTargets); + GSIMapEmptyMap(_localTargets); + NSZoneFree(_localTargets->zone, (void*)_localTargets); _localTargets = 0; } if (_remoteProxies != 0) { - NSFreeMapTable(_remoteProxies); + GSIMapEmptyMap(_remoteProxies); + NSZoneFree(_remoteProxies->zone, (void*)_remoteProxies); _remoteProxies = 0; } if (_localObjects != 0) { - NSFreeMapTable(_localObjects); + GSIMapNode node = _localObjects->firstNode; + + while (node != 0) + { + RELEASE(node->key.obj); + node = node->nextInMap; + } + GSIMapEmptyMap(_localObjects); + NSZoneFree(_localObjects->zone, (void*)_localObjects); _localObjects = 0; } M_UNLOCK(_proxiesGate); @@ -905,11 +933,18 @@ static NSLock *global_proxies_gate; - (NSArray*) localObjects { - NSArray *c; + NSMutableArray *c; + GSIMapNode node; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - c = NSAllMapTableValues(_localObjects); + c = [NSMutableArray arrayWithCapacity: _localObjects->nodeCount]; + node = _localObjects->firstNode; + while (node != 0) + { + [c addObject: node->key.obj]; + node = node->nextInMap; + } M_UNLOCK(_proxiesGate); return c; } @@ -970,11 +1005,18 @@ static NSLock *global_proxies_gate; - (NSArray *) remoteObjects { - NSArray *c; + NSMutableArray *c; + GSIMapNode node; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - c = NSAllMapTableValues(_remoteProxies); + c = [NSMutableArray arrayWithCapacity: _remoteProxies->nodeCount]; + node = _remoteProxies->firstNode; + while (node != 0) + { + [c addObject: node->key.obj]; + node = node->nextInMap; + } M_UNLOCK(_proxiesGate); return c; } @@ -1048,8 +1090,7 @@ static NSLock *global_proxies_gate; NSParameterAssert(_receivePort); NSParameterAssert(_isValid); - seq_num = [self _newMsgNumber]; - op = [self _makeOutRmc: seq_num]; + op = [self _makeOutRmc: 0 generate: &seq_num reply: YES]; [self _sendOutRmc: op type: ROOTPROXY_REQUEST]; ip = [self _getReplyRmc: seq_num]; @@ -1142,10 +1183,14 @@ static NSLock *global_proxies_gate; /* * These are GNUstep extras */ - o = [NSNumber numberWithUnsignedInt: NSCountMapTable(_localTargets)]; + o = [NSNumber numberWithUnsignedInt: _localTargets->nodeCount]; [d setObject: o forKey: NSConnectionLocalCount]; - o = [NSNumber numberWithUnsignedInt: NSCountMapTable(_remoteProxies)]; + o = [NSNumber numberWithUnsignedInt: _remoteProxies->nodeCount]; [d setObject: o forKey: NSConnectionProxyCount]; + o = [NSNumber numberWithUnsignedInt: _replyMap->nodeCount]; + [d setObject: o forKey: @"NSConnectionReplyQueue"]; + o = [NSNumber numberWithUnsignedInt: [_requestQueue count]]; + [d setObject: o forKey: @"NSConnectionRequestQueue"]; M_UNLOCK(_refGate); @@ -1214,7 +1259,16 @@ static NSLock *global_proxies_gate; DESTROY(_requestQueue); if (_replyMap != 0) { - NSFreeMapTable(_replyMap); + GSIMapNode node = _replyMap->firstNode; + + while (node != 0) + { + if (node->key.obj != dummyObject) + RELEASE(node->key.obj); + node = node->nextInMap; + } + GSIMapEmptyMap(_replyMap); + NSZoneFree(_replyMap->zone, (void*)_replyMap); _replyMap = 0; } @@ -1233,7 +1287,12 @@ static NSLock *global_proxies_gate; selector: (SEL)sel argFrame: (arglist_t)argframe { - NSPortCoder *op; + NSPortCoder *op; + BOOL outParams; + BOOL needsResponse; + const char *type; + int seq_num; + retval_t retframe; /* The callback for encoding the args of the method call. */ void encoder (int argnum, void *datum, const char *type, int flags) @@ -1257,57 +1316,87 @@ static NSLock *global_proxies_gate; } /* Encode the method on an RMC, and send it. */ - { - BOOL out_parameters; - const char *type; - int seq_num; - retval_t retframe; - NSParameterAssert (_isValid); + NSParameterAssert (_isValid); - /* get the method types from the selector */ + /* get the method types from the selector */ #if NeXT_runtime - [NSException - raise: NSGenericException - format: @"Sorry, distributed objects does not work with NeXT runtime"]; - /* type = [object selectorTypeForProxy: sel]; */ + [NSException + raise: NSGenericException + format: @"Sorry, distributed objects does not work with NeXT runtime"]; + /* type = [object selectorTypeForProxy: sel]; */ #else - type = sel_get_type(sel); + type = sel_get_type(sel); #endif - if (type == 0 || *type == '\0') { - type = [[object methodSignatureForSelector: sel] methodType]; - if (type) { - sel_register_typed_name(sel_get_name(sel), type); + if (type == 0 || *type == '\0') + { + type = [[object methodSignatureForSelector: sel] methodType]; + if (type) + { + sel_register_typed_name(sel_get_name(sel), type); } } - NSParameterAssert(type); - NSParameterAssert(*type); + NSParameterAssert(type); + NSParameterAssert(*type); - seq_num = [self _newMsgNumber]; - op = [self _makeOutRmc: seq_num]; + op = [self _makeOutRmc: 0 generate: &seq_num reply: YES]; - if (debug_connection > 4) - NSLog(@"building packet seq %d", seq_num); + if (debug_connection > 4) + NSLog(@"building packet seq %d", seq_num); - /* Send the types that we're using, so that the performer knows - exactly what qualifiers we're using. - If all selectors included qualifiers, and if I could make - sel_types_match() work the way I wanted, we wouldn't need to do - this. */ - [op encodeValueOfObjCType: @encode(char*) at: &type]; + /* Send the types that we're using, so that the performer knows + exactly what qualifiers we're using. + If all selectors included qualifiers, and if I could make + sel_types_match() work the way I wanted, we wouldn't need to do + this. */ + [op encodeValueOfObjCType: @encode(char*) at: &type]; - /* xxx This doesn't work with proxies and the NeXT runtime because - type may be a method_type from a remote machine with a - different architecture, and its argframe layout specifiers - won't be right for this machine! */ - out_parameters = mframe_dissect_call (argframe, type, encoder); + /* xxx This doesn't work with proxies and the NeXT runtime because + type may be a method_type from a remote machine with a + different architecture, and its argframe layout specifiers + won't be right for this machine! */ + outParams = mframe_dissect_call (argframe, type, encoder); - [self _sendOutRmc: op type: METHOD_REQUEST]; + if (outParams == YES) + { + needsResponse = YES; + } + else + { + int flags; - if (debug_connection > 1) - NSLog(@"Sent message to 0x%x", (gsaddr)self); + needsResponse = NO; + flags = objc_get_type_qualifiers(type); + if ((flags & _F_ONEWAY) == 0) + { + needsResponse = YES; + } + else + { + const char *tmptype = objc_skip_type_qualifiers(type); - /* Get the reply rmc, and decode it. */ + if (*tmptype != _C_VOID) + { + needsResponse = YES; + } + } + } + + [self _sendOutRmc: op type: METHOD_REQUEST]; + NSDebugMLLog(@"NSConnection", @"Sent message to 0x%x", (gsaddr)self); + + if (needsResponse == NO) + { + /* + * Since we don't need a response, we can remove the placeholder from + * the _replyMap. + */ + M_LOCK(_refGate); + GSIMapRemoveKey(_replyMap, (GSIMapKey)seq_num); + M_UNLOCK(_refGate); + retframe = alloca(sizeof(void*)); /* Dummy value for void return. */ + } + else { NSPortCoder *ip = nil; BOOL is_exception = NO; @@ -1330,14 +1419,14 @@ static NSLock *global_proxies_gate; { if (!_isValid) { - [NSException raise: NSGenericException - format: @"connection waiting for request was shut down"]; + [NSException raise: NSGenericException + format: @"connection waiting for request was shut down"]; } - /* xxx Why do we get the reply packet in here, and not - just before calling dissect_method_return() below? */ ip = [self _getReplyRmc: seq_num]; - /* Find out if the server is returning an exception instead - of the return values. */ + /* + * Find out if the server is returning an exception instead + * of the return values. + */ [ip decodeValueOfObjCType: @encode(BOOL) at: &is_exception]; if (is_exception) { @@ -1352,26 +1441,25 @@ static NSLock *global_proxies_gate; } } [ip decodeValueOfObjCType: type at: datum]; - /* -decodeValueOfObjCType: at: malloc's new memory - for char*'s. We need to make sure it gets freed eventually + /* -decodeValueOfObjCType:at: malloc's new memory + for pointers. We need to make sure it gets freed eventually so we don't have a memory leak. Request here that it be autorelease'ed. Also autorelease created objects. */ if ((*type == _C_CHARPTR || *type == _C_PTR) && *(void**)datum != 0) [NSData dataWithBytesNoCopy: *(void**)datum length: 1]; - else if (*type == _C_ID) - AUTORELEASE(*(id*)datum); + else if (*type == _C_ID) + AUTORELEASE(*(id*)datum); } - retframe = mframe_build_return (argframe, type, out_parameters, decoder); + retframe = mframe_build_return (argframe, type, outParams, decoder); /* Make sure we processed all arguments, and dismissed the IP. - IP is always set to -1 after being dismissed; the only places + IP is always set to -1 after being dismissed; the only places this is done is in this function DECODER(). IP will be nil if mframe_build_return() never called DECODER(), i.e. when we are just returning (void).*/ NSAssert(ip == (id)-1 || ip == nil, NSInternalInconsistencyException); - return retframe; } - } + return retframe; } - (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target @@ -1382,8 +1470,7 @@ static NSLock *global_proxies_gate; NSParameterAssert(_receivePort); NSParameterAssert (_isValid); - seq_num = [self _newMsgNumber]; - op = [self _makeOutRmc: seq_num]; + op = [self _makeOutRmc: 0 generate: &seq_num reply: YES]; [op encodeValueOfObjCType: ":" at: &sel]; [op encodeValueOfObjCType: @encode(unsigned) at: &target]; [self _sendOutRmc: op type: METHODTYPE_REQUEST]; @@ -1543,11 +1630,27 @@ static NSLock *global_proxies_gate; case METHODTYPE_REPLY: case RETAIN_REPLY: { - int sequence; + int sequence; + GSIMapNode node; [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; M_LOCK(conn->_queueGate); - NSMapInsert(conn->_replyMap, (void*)sequence, rmc); + node = GSIMapNodeForKey(conn->_replyMap, (GSIMapKey)sequence); + if (node == 0) + { + NSDebugMLLog(@"NSConnection", @"Ignoring RMC %d", sequence); + RELEASE(rmc); + } + else if (node->value.obj == dummyObject) + { + node->value.obj = rmc; + } + else + { + NSDebugMLLog(@"NSConnection", @"Replace RMC %d", sequence); + RELEASE(node->value.obj); + node->value.obj = rmc; + } M_UNLOCK(conn->_queueGate); } break; @@ -1591,7 +1694,7 @@ static NSLock *global_proxies_gate; { char *forward_type = 0; id op = nil; - int reply_sequence_number; + int reply_sno; void decoder (int argnum, void *datum, const char *type) { @@ -1625,7 +1728,7 @@ static NSLock *global_proxies_gate; back to the remote application! */ if (!_isValid) return; - op = [self _makeOutRmc: reply_sequence_number]; + op = [self _makeOutRmc: reply_sno generate: 0 reply: NO]; [op encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; } switch (*type) @@ -1652,7 +1755,7 @@ static NSLock *global_proxies_gate; NSParameterAssert (_isValid); /* Save this for later */ - [aRmc decodeValueOfObjCType: @encode(int) at: &reply_sequence_number]; + [aRmc decodeValueOfObjCType: @encode(int) at: &reply_sno]; /* Get the types that we're using, so that we know exactly what qualifiers the forwarder used. @@ -1681,7 +1784,7 @@ static NSLock *global_proxies_gate; { NS_DURING { - op = [self _makeOutRmc: reply_sequence_number]; + op = [self _makeOutRmc: reply_sno generate: 0 reply: NO]; [op encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; [op encodeBycopyObject: localException]; @@ -1714,7 +1817,7 @@ static NSLock *global_proxies_gate; [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; [self _doneInRmc: rmc]; - op = [self _makeOutRmc: sequence]; + op = [self _makeOutRmc: sequence generate: 0 reply: NO]; [op encodeObject: rootObject]; [self _sendOutRmc: op type: ROOTPROXY_REPLY]; } @@ -1761,7 +1864,7 @@ static NSLock *global_proxies_gate; NSParameterAssert (_isValid); [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; - op = [self _makeOutRmc: sequence]; + op = [self _makeOutRmc: sequence generate: 0 reply: NO]; [rmc decodeValueOfObjCType: @encode(typeof(target)) at: &target]; [self _doneInRmc: rmc]; @@ -1828,10 +1931,11 @@ static NSLock *global_proxies_gate; - (void) shutdown { NSPortCoder *op; + int sno; NSParameterAssert(_receivePort); NSParameterAssert (_isValid); - op = [self _makeOutRmc: [self _newMsgNumber]]; + op = [self _makeOutRmc: 0 generate: &sno reply: NO]; [self _sendOutRmc: op type: CONNECTION_SHUTDOWN]; } @@ -1859,7 +1963,7 @@ static NSLock *global_proxies_gate; NSParameterAssert (_isValid); [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; - op = [self _makeOutRmc: sequence]; + op = [self _makeOutRmc: sequence generate: 0 reply: NO]; [rmc decodeValueOfObjCType: ":" at: &sel]; [rmc decodeValueOfObjCType: @encode(unsigned) at: &target]; @@ -1891,45 +1995,53 @@ static NSLock *global_proxies_gate; - _getReplyRmc: (int)sn { NSPortCoder *rmc; + GSIMapNode node; NSDate *timeout_date = nil; M_LOCK(_queueGate); - while ((rmc = (NSPortCoder*)NSMapGet(_replyMap, (void*)sn)) == nil) + while ((node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn)) != 0 + && node->value.obj == dummyObject) { if (timeout_date == nil) { + timeout_date = [dateClass allocWithZone: NSDefaultMallocZone()]; timeout_date - = [dateClass dateWithTimeIntervalSinceNow: _replyTimeout]; + = [timeout_date initWithTimeIntervalSinceNow: _replyTimeout]; } M_UNLOCK(_queueGate); if ([runLoopClass runOnceBeforeDate: timeout_date forMode: NSConnectionReplyMode] == NO) { - [NSException raise: NSPortTimeoutException - format: @"timed out waiting for reply"]; + M_LOCK(_queueGate); + node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn); + break; } M_LOCK(_queueGate); } - if (rmc != nil) + if (node == 0) { - RETAIN(rmc); - NSMapRemove(_replyMap, (void*)sn); + rmc = nil; + } + else + { + rmc = node->value.obj; + GSIMapRemoveKey(_replyMap, (GSIMapKey)sn); } M_UNLOCK(_queueGate); + TEST_RELEASE(timeout_date); + if (rmc == nil) + { + [NSException raise: NSInternalInconsistencyException + format: @"no reply message available"]; + } + if (rmc == dummyObject) + { + [NSException raise: NSPortTimeoutException + format: @"timed out waiting for reply"]; + } return rmc; } -- (int) _newMsgNumber -{ - int n; - - NSParameterAssert (_isValid); - M_LOCK(sequenceNumberGate); - n = _messageCount++; - M_UNLOCK(sequenceNumberGate); - return n; -} - - (void) _doneInRmc: (NSPortCoder*)c { M_LOCK(_refGate); @@ -1966,7 +2078,16 @@ static NSLock *global_proxies_gate; return coder; } -- (NSPortCoder*) _makeOutRmc: (int)sequence +/* + * Create an NSPortCoder object for encoding an outgoing message or reply. + * + * sno Is the seqence number to encode into the coder. + * ret If non-null, generate a new sequence number and return it + * here. Ignore the sequence number passed in sno. + * rep If this flag is YES, add a placeholder to the _replyMap + * so we handle an incoming reply for this sequence number. + */ +- (NSPortCoder*) _makeOutRmc: (int)sno generate: (int*)ret reply: (BOOL)rep { NSPortCoder *coder; unsigned count; @@ -1974,6 +2095,24 @@ static NSLock *global_proxies_gate; NSParameterAssert(_isValid); M_LOCK(_refGate); + /* + * Generate a new sequence number if required. + */ + if (ret != 0) + { + sno = _messageCount++; + *ret = sno; + } + /* + * Add a placeholder to the reply map if we expect a reply. + */ + if (rep == YES) + { + GSIMapAddPair(_replyMap, (GSIMapKey)sno, (GSIMapVal)dummyObject); + } + /* + * Locate or create an rmc + */ count = [_cachedEncoders count]; if (count > 0) { @@ -1990,7 +2129,7 @@ static NSLock *global_proxies_gate; coder = [coder initWithReceivePort: _receivePort sendPort: _sendPort components: nil]; - [coder encodeValueOfObjCType: @encode(int) at: &sequence]; + [coder encodeValueOfObjCType: @encode(int) at: &sno]; return coder; } @@ -2033,9 +2172,9 @@ static NSLock *global_proxies_gate; case METHOD_REQUEST: case ROOTPROXY_REQUEST: case METHODTYPE_REQUEST: + needsReply = YES; default: raiseException = YES; - needsReply = YES; break; } @@ -2110,13 +2249,27 @@ static NSLock *global_proxies_gate; id object = [anObj localForProxy]; unsigned target; GSLocalCounter *counter; + GSIMapNode node; + NSParameterAssert (_isValid); M_LOCK(_proxiesGate); M_LOCK(global_proxies_gate); - /* xxx Do we need to check to make sure it's not already there? */ - /* This retains object. */ - NSMapInsert(_localObjects, (void*)object, anObj); + + /* + * Record the value in the _localObjects map, retaining it. + */ + node = GSIMapNodeForKey(_localObjects, (GSIMapKey)object); + IF_NO_GC(RETAIN(anObj)); + if (node) + { + RELEASE(node->value.obj); + node->value.obj = anObj; + } + else + { + GSIMapAddPair(_localObjects, (GSIMapKey)object, (GSIMapVal)anObj); + } /* * Keep track of local objects accross all connections. @@ -2136,7 +2289,7 @@ static NSLock *global_proxies_gate; RELEASE(counter); } [anObj setProxyTarget: target]; - NSMapInsert(_localTargets, (void*)target, anObj); + GSIMapAddPair(_localTargets, (GSIMapKey)target, (GSIMapVal)anObj); if (debug_connection > 2) NSLog(@"add local object (0x%x) target (0x%x) " @"to connection (0x%x) (ref %d)", @@ -2147,13 +2300,22 @@ static NSLock *global_proxies_gate; - (NSDistantObject*) localForObject: (id)object { - NSDistantObject *p; + GSIMapNode node; + NSDistantObject *p; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - p = NSMapGet (_localObjects, (void*)object); + node = GSIMapNodeForKey(_localObjects, (GSIMapKey)object); + if (node == 0) + { + p = nil; + } + else + { + p = node->value.obj; + } M_UNLOCK(_proxiesGate); - NSParameterAssert(!p || [p connectionForProxy] == self); + NSParameterAssert(p == nil || [p connectionForProxy] == self); return p; } @@ -2176,11 +2338,20 @@ static NSLock *global_proxies_gate; unsigned target; GSLocalCounter *counter; unsigned val = 0; + GSIMapNode node; M_LOCK(global_proxies_gate); M_LOCK(_proxiesGate); - prox = NSMapGet(_localObjects, (void*)anObj); + node = GSIMapNodeForKey(_localObjects, (GSIMapKey)anObj); + if (node == 0) + { + prox = nil; + } + else + { + prox = node->value.obj; + } target = [prox targetForProxy]; /* @@ -2221,8 +2392,16 @@ static NSLock *global_proxies_gate; } } - NSMapRemove(_localObjects, (void*)anObj); - NSMapRemove(_localTargets, (void*)target); + /* + * Remove the proxy from _localObjects and release it. + */ + GSIMapRemoveKey(_localObjects, (GSIMapKey)anObj); + RELEASE(prox); + + /* + * Remove the target info too - no release required. + */ + GSIMapRemoveKey(_localTargets, (GSIMapKey)target); if (debug_connection > 2) NSLog(@"remove local object (0x%x) target (0x%x) " @@ -2246,9 +2425,9 @@ static NSLock *global_proxies_gate; { id op; unsigned i; - int sequence = [self _newMsgNumber]; + int sequence; - op = [self _makeOutRmc: sequence]; + op = [self _makeOutRmc: 0 generate: &sequence reply: NO]; [op encodeValueOfObjCType: @encode(unsigned) at: &number]; @@ -2284,9 +2463,9 @@ static NSLock *global_proxies_gate; NSPortCoder *op; id ip; id result; - int seq_num = [self _newMsgNumber]; + int seq_num; - op = [self _makeOutRmc: seq_num]; + op = [self _makeOutRmc: 0 generate: &seq_num reply: YES]; [op encodeValueOfObjCType: @encode(typeof(target)) at: &target]; [self _sendOutRmc: op type: PROXY_RETAIN]; @@ -2311,7 +2490,7 @@ static NSLock *global_proxies_gate; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); /* This also releases aProxy */ - NSMapRemove(_remoteProxies, (void*)target); + GSIMapRemoveKey(_remoteProxies, (GSIMapKey)target); M_UNLOCK(_proxiesGate); /* @@ -2323,41 +2502,60 @@ static NSLock *global_proxies_gate; - (NSDistantObject*) proxyForTarget: (unsigned)target { - NSDistantObject *p; + NSDistantObject *p; + GSIMapNode node; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - p = NSMapGet(_remoteProxies, (void*)target); + node = GSIMapNodeForKey(_remoteProxies, (GSIMapKey)target); + if (node == 0) + { + p = nil; + } + else + { + p = node->value.obj; + } M_UNLOCK(_proxiesGate); - NSParameterAssert(!p || [p connectionForProxy] == self); return p; } - (void) addProxy: (NSDistantObject*) aProxy { - unsigned target = (unsigned int)[aProxy targetForProxy]; + unsigned target = (unsigned int)[aProxy targetForProxy]; + GSIMapNode node; NSParameterAssert (_isValid); NSParameterAssert(aProxy->isa == distantObjectClass); NSParameterAssert([aProxy connectionForProxy] == self); M_LOCK(_proxiesGate); - if (NSMapGet(_remoteProxies, (void*)target)) + node = GSIMapNodeForKey(_remoteProxies, (GSIMapKey)target); + if (node != 0) { M_UNLOCK(_proxiesGate); [NSException raise: NSGenericException format: @"Trying to add the same proxy twice"]; } - NSMapInsert(_remoteProxies, (void*)target, aProxy); + GSIMapAddPair(_remoteProxies, (GSIMapKey)target, (GSIMapVal)aProxy); M_UNLOCK(_proxiesGate); } - (id) includesProxyForTarget: (unsigned)target { NSDistantObject *ret; + GSIMapNode node; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - ret = NSMapGet (_remoteProxies, (void*)target); + node = GSIMapNodeForKey(_remoteProxies, (GSIMapKey)target); + if (node == 0) + { + ret = nil; + } + else + { + ret = node->value.obj; + } M_UNLOCK(_proxiesGate); return ret; } @@ -2365,10 +2563,19 @@ static NSLock *global_proxies_gate; - (id) includesLocalObject: (id)anObj { NSDistantObject *ret; + GSIMapNode node; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - ret = NSMapGet(_localObjects, (void*)anObj); + node = GSIMapNodeForKey(_localObjects, (GSIMapKey)anObj); + if (node == 0) + { + ret = nil; + } + else + { + ret = node->value.obj; + } M_UNLOCK(_proxiesGate); return ret; } @@ -2376,10 +2583,19 @@ static NSLock *global_proxies_gate; - (id) includesLocalTarget: (unsigned)target { NSDistantObject *ret; + GSIMapNode node; /* Don't assert (_isValid); */ M_LOCK(_proxiesGate); - ret = NSMapGet(_localTargets, (void*)target); + node = GSIMapNodeForKey(_localTargets, (GSIMapKey)target); + if (node == 0) + { + ret = nil; + } + else + { + ret = node->value.obj; + } M_UNLOCK(_proxiesGate); return ret; } @@ -2900,6 +3116,8 @@ static int messages_received_count; is_valid = NO; + NSHashRemove(connection_table, self); + /* * Don't need notifications any more - so remove self as observer. */ diff --git a/Source/NSDistantObject.m b/Source/NSDistantObject.m index 7aee7f6f1..13dc69bcf 100644 --- a/Source/NSDistantObject.m +++ b/Source/NSDistantObject.m @@ -271,7 +271,7 @@ enum */ if ((proxy = [aConnection localForObject: anObject])) { - return [proxy retain]; + return RETAIN(proxy); } proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass, @@ -291,7 +291,7 @@ enum */ if ((proxy = [aConnection proxyForTarget: target])) { - return [proxy retain]; + return RETAIN(proxy); } proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass, @@ -329,15 +329,15 @@ enum + (NSDistantObject*) proxyWithLocal: (id)anObject connection: (NSConnection*)aConnection { - return [[placeHolder initWithLocal: anObject - connection: aConnection] autorelease]; + return AUTORELEASE([placeHolder initWithLocal: anObject + connection: aConnection]); } + (NSDistantObject*) proxyWithTarget: (unsigned)anObject connection: (NSConnection*)aConnection { - return [[placeHolder initWithTarget: anObject - connection: aConnection] autorelease]; + return AUTORELEASE([placeHolder initWithTarget: anObject + connection: aConnection]); } - (NSConnection*) connectionForProxy @@ -481,7 +481,7 @@ enum /* if ([aCoder isKindOfClass: [NSPortCoder class]] == NO) { - [self release]; + RELEASE(self); [NSException raise: NSGenericException format: @"NSDistantObject objects only decode with " @"NSPortCoder class"]; @@ -513,7 +513,7 @@ enum if (![[decoder_connection class] includesLocalTarget: target]) { - [self release]; + RELEASE(self); [NSException raise: @"ProxyDecodedBadTarget" format: @"No local object with given target (0x%x)", target]; @@ -528,8 +528,8 @@ enum NSLog(@"Local object is 0x%x (0x%x)\n", (gsaddr)o, (gsaddr)o ? o->_object : 0); } - [self release]; - return o ? [o->_object retain] : nil; + RELEASE(self); + return o ? RETAIN(o->_object) : nil; } case PROXY_LOCAL_FOR_SENDER: @@ -545,9 +545,9 @@ enum if (debug_proxy) NSLog(@"Receiving a proxy, was local 0x%x connection 0x%x\n", target, (gsaddr)decoder_connection); - [self release]; - return [[NSDistantObject proxyWithTarget: target - connection: decoder_connection] retain]; + RELEASE(self); + return RETAIN([NSDistantObject proxyWithTarget: target + connection: decoder_connection]); case PROXY_REMOTE_FOR_BOTH: /* @@ -627,9 +627,9 @@ enum if ([proxy_connection includesProxyForTarget: target] == NO) [proxy_connection retainTarget: target]; - result = [[NSDistantObject proxyWithTarget: target - connection: proxy_connection] retain]; - [self release]; + result = RETAIN([NSDistantObject proxyWithTarget: target + connection: proxy_connection]); + RELEASE(self); /* * Finally - we have a proxy via a direct connection to the @@ -643,7 +643,7 @@ enum default: /* xxx This should be something different than NSGenericException. */ - [self release]; + RELEASE(self); [NSException raise: NSGenericException format: @"Bad proxy tag"]; } @@ -663,8 +663,9 @@ enum */ if ((new_proxy = [aConnection localForObject: anObject])) { - [self release]; - return [new_proxy retain]; + RETAIN(new_proxy); + RELEASE(self); + return new_proxy; } /* @@ -677,7 +678,7 @@ enum /* * We register this proxy with the connection using it. */ - _connection = [aConnection retain]; + _connection = RETAIN(aConnection); [_connection addLocalObject: self]; if (debug_proxy) @@ -699,8 +700,9 @@ enum */ if ((new_proxy = [aConnection proxyForTarget: target])) { - [self release]; - return [new_proxy retain]; + RETAIN(new_proxy); + RELEASE(self); + return new_proxy; } _object = nil; @@ -710,7 +712,7 @@ enum * We retain our connection so it can't disappear while the app * may want to use it. */ - _connection = [aConnection retain]; + _connection = RETAIN(aConnection); /* * We register this object with the connection using it. @@ -808,7 +810,7 @@ enum */ if (_object == nil) [_connection removeProxy: self]; - [_connection release]; + RELEASE(_connection); } } diff --git a/Source/NSPortNameServer.m b/Source/NSPortNameServer.m index 8f3022054..ae597f451 100644 --- a/Source/NSPortNameServer.m +++ b/Source/NSPortNameServer.m @@ -361,7 +361,7 @@ typedef enum { NS_DURING { - handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: + handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: hostname service: serverPort protocol: @"tcp" forModes: modes]; } NS_HANDLER @@ -383,26 +383,34 @@ typedef enum { if (handle == nil) { - NSLog(@"Failed to find gdomap port with name '%@',\nperhaps your " - @"/etc/services file is not correctly set up?\n" - @"Retrying with default (IANA allocated) port number 538", - serverPort); - NS_DURING + if (state == GSPC_LOPEN) { - handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: - hostname service: @"538" protocol: @"tcp" forModes: modes]; + NSLog(@"Failed to find gdomap port with name '%@',\nperhaps your " + @"/etc/services file is not correctly set up?\n" + @"Retrying with default (IANA allocated) port number 538", + serverPort); + NS_DURING + { + handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: + hostname service: @"538" protocol: @"tcp" forModes: modes]; + } + NS_HANDLER + { + NSLog(@"Exception creating handle for gdomap - %@", + localException); + [self fail]; + } + NS_ENDHANDLER + if (handle) + { + RELEASE(serverPort); + serverPort = @"538"; + } } - NS_HANDLER + else { - NSLog(@"Exception creating handle for gdomap - %@", localException); [self fail]; } - NS_ENDHANDLER - if (handle) - { - RELEASE(serverPort); - serverPort = @"538"; - } } if (state == GSPC_FAIL)