DO tidyups

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6875 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 2000-07-05 12:23:00 +00:00
parent be0c0ae006
commit b5cd1a215b
5 changed files with 431 additions and 187 deletions

View file

@ -1,3 +1,13 @@
2000-07-05 Richard Frith-Macdonald <rfm@gnu.org>
* 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 <rfm@gnu.org> 2000-07-04 Richard Frith-Macdonald <rfm@gnu.org>
* Makefile.preamble: define GS_NEW_DO to specify whether the * Makefile.preamble: define GS_NEW_DO to specify whether the

View file

@ -73,10 +73,16 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */
unsigned _reqInCount; unsigned _reqInCount;
unsigned _repOutCount; unsigned _repOutCount;
unsigned _repInCount; unsigned _repInCount;
NSMapTable *_localObjects; #ifndef _IN_CONNECTION_M
NSMapTable *_localTargets; #define GSIMapTable void*
NSMapTable *_remoteProxies; #endif
NSMapTable *_replyMap; GSIMapTable _localObjects;
GSIMapTable _localTargets;
GSIMapTable _remoteProxies;
GSIMapTable _replyMap;
#ifndef _IN_CONNECTION_M
#undef GSIMapTable
#endif
NSTimeInterval _replyTimeout; NSTimeInterval _replyTimeout;
NSTimeInterval _requestTimeout; NSTimeInterval _requestTimeout;
NSMutableArray *_requestModes; NSMutableArray *_requestModes;

View file

@ -30,7 +30,22 @@
#include <base/preface.h> #include <base/preface.h>
#include <mframe.h> #include <mframe.h>
/*
* 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 <base/GSIMap.h>
#define _IN_CONNECTION_M
#include <Foundation/NSConnection.h> #include <Foundation/NSConnection.h>
#undef _IN_CONNECTION_M
#include <Foundation/NSPortCoder.h> #include <Foundation/NSPortCoder.h>
#include <Foundation/DistributedObjects.h> #include <Foundation/DistributedObjects.h>
@ -57,6 +72,7 @@
#define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];} #define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
#define M_UNLOCK(X) {NSDebugMLLog(@"GSConnection",@"Unlock %@",X);[X unlock];} #define M_UNLOCK(X) {NSDebugMLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
static id dummyObject;
static Class connectionClass; static Class connectionClass;
static Class dateClass; static Class dateClass;
static Class distantObjectClass; static Class distantObjectClass;
@ -213,8 +229,7 @@ static unsigned local_object_counter = 0;
- (void) _doneInRmc: (NSPortCoder*)c; - (void) _doneInRmc: (NSPortCoder*)c;
- (NSPortCoder*) _getReplyRmc: (int)sn; - (NSPortCoder*) _getReplyRmc: (int)sn;
- (NSPortCoder*) _makeInRmc: (NSMutableArray*)components; - (NSPortCoder*) _makeInRmc: (NSMutableArray*)components;
- (NSPortCoder*) _makeOutRmc: (int)sequence; - (NSPortCoder*) _makeOutRmc: (int)sequence generate: (int*)sno reply: (BOOL)f;
- (int) _newMsgNumber;
- (void) _sendOutRmc: (NSPortCoder*)c type: (int)msgid; - (void) _sendOutRmc: (NSPortCoder*)c type: (int)msgid;
- (void) _service_forwardForProxy: (NSPortCoder*)rmc; - (void) _service_forwardForProxy: (NSPortCoder*)rmc;
@ -227,7 +242,6 @@ static unsigned local_object_counter = 0;
#define _proxiesGate _refGate #define _proxiesGate _refGate
#define _queueGate _refGate #define _queueGate _refGate
#define sequenceNumberGate _refGate
/* class defaults */ /* class defaults */
@ -427,6 +441,8 @@ static NSLock *global_proxies_gate;
portCoderClass = [NSPortCoder class]; portCoderClass = [NSPortCoder class];
runLoopClass = [NSRunLoop class]; runLoopClass = [NSRunLoop class];
dummyObject = [NSObject new];
connection_table = connection_table =
NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0); NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
connection_table_gate = [NSLock new]; connection_table_gate = [NSLock new];
@ -595,6 +611,7 @@ static NSLock *global_proxies_gate;
NSConnection *conn; NSConnection *conn;
NSRunLoop *loop; NSRunLoop *loop;
id del; id del;
NSZone *z = NSDefaultMallocZone();
/* /*
* If the receive port is nil, deallocate connection and return nil. * 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 * This maps request sequence numbers to the NSPortCoder objects representing
* replies arriving from the remote connection. * replies arriving from the remote connection.
*/ */
_replyMap = _replyMap = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t));
NSCreateMapTable(NSIntMapKeyCallBacks, GSIMapInitWithZoneAndCapacity(_replyMap, z, 4);
NSObjectMapValueCallBacks, 0);
/* /*
* This maps (void*)obj to (id)obj. The obj's are retained. * This maps (void*)obj to (id)obj. The obj's are retained.
* We use this instead of an NSHashTable because we only care about * 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. * the object's address, and don't want to send the -hash message to it.
*/ */
_localObjects = _localObjects = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t));
NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, GSIMapInitWithZoneAndCapacity(_localObjects, z, 4);
NSObjectMapValueCallBacks, 0);
/* /*
* This maps handles for local objects to their local proxies. * This maps handles for local objects to their local proxies.
*/ */
_localTargets = _localTargets = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t));
NSCreateMapTable(NSIntMapKeyCallBacks, GSIMapInitWithZoneAndCapacity(_localTargets, z, 4);
NSNonOwnedPointerMapValueCallBacks, 0);
/* /*
* This maps [proxy targetForProxy] to proxy. The proxy's are retained. * This maps [proxy targetForProxy] to proxy. The proxy's are retained.
*/ */
_remoteProxies = _remoteProxies = (GSIMapTable)NSZoneMalloc(z, sizeof(GSIMapTable_t));
NSCreateMapTable(NSIntMapKeyCallBacks, GSIMapInitWithZoneAndCapacity(_remoteProxies, z, 4);
NSNonOwnedPointerMapValueCallBacks, 0);
_requestDepth = 0; _requestDepth = 0;
_delegate = nil; _delegate = nil;
@ -867,12 +880,17 @@ static NSLock *global_proxies_gate;
M_LOCK(_proxiesGate); M_LOCK(_proxiesGate);
if (_localTargets != 0) if (_localTargets != 0)
{ {
NSArray *targets; NSMutableArray *targets;
unsigned i; unsigned i = _localTargets->nodeCount;
GSIMapNode node;
targets = NSAllMapTableValues(_localTargets); targets = [[NSMutableArray alloc] initWithCapacity: i];
IF_NO_GC(RETAIN(targets)); node = _localTargets->firstNode;
i = [targets count]; while (node != 0)
{
[targets addObject: node->value.obj];
node = node->nextInMap;
}
while (i-- > 0) while (i-- > 0)
{ {
id t = [[targets objectAtIndex: i] localForProxy]; id t = [[targets objectAtIndex: i] localForProxy];
@ -880,17 +898,27 @@ static NSLock *global_proxies_gate;
[self removeLocalObject: t]; [self removeLocalObject: t];
} }
RELEASE(targets); RELEASE(targets);
NSFreeMapTable(_localTargets); GSIMapEmptyMap(_localTargets);
NSZoneFree(_localTargets->zone, (void*)_localTargets);
_localTargets = 0; _localTargets = 0;
} }
if (_remoteProxies != 0) if (_remoteProxies != 0)
{ {
NSFreeMapTable(_remoteProxies); GSIMapEmptyMap(_remoteProxies);
NSZoneFree(_remoteProxies->zone, (void*)_remoteProxies);
_remoteProxies = 0; _remoteProxies = 0;
} }
if (_localObjects != 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; _localObjects = 0;
} }
M_UNLOCK(_proxiesGate); M_UNLOCK(_proxiesGate);
@ -905,11 +933,18 @@ static NSLock *global_proxies_gate;
- (NSArray*) localObjects - (NSArray*) localObjects
{ {
NSArray *c; NSMutableArray *c;
GSIMapNode node;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
return c; return c;
} }
@ -970,11 +1005,18 @@ static NSLock *global_proxies_gate;
- (NSArray *) remoteObjects - (NSArray *) remoteObjects
{ {
NSArray *c; NSMutableArray *c;
GSIMapNode node;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
return c; return c;
} }
@ -1048,8 +1090,7 @@ static NSLock *global_proxies_gate;
NSParameterAssert(_receivePort); NSParameterAssert(_receivePort);
NSParameterAssert(_isValid); NSParameterAssert(_isValid);
seq_num = [self _newMsgNumber]; op = [self _makeOutRmc: 0 generate: &seq_num reply: YES];
op = [self _makeOutRmc: seq_num];
[self _sendOutRmc: op type: ROOTPROXY_REQUEST]; [self _sendOutRmc: op type: ROOTPROXY_REQUEST];
ip = [self _getReplyRmc: seq_num]; ip = [self _getReplyRmc: seq_num];
@ -1142,10 +1183,14 @@ static NSLock *global_proxies_gate;
/* /*
* These are GNUstep extras * These are GNUstep extras
*/ */
o = [NSNumber numberWithUnsignedInt: NSCountMapTable(_localTargets)]; o = [NSNumber numberWithUnsignedInt: _localTargets->nodeCount];
[d setObject: o forKey: NSConnectionLocalCount]; [d setObject: o forKey: NSConnectionLocalCount];
o = [NSNumber numberWithUnsignedInt: NSCountMapTable(_remoteProxies)]; o = [NSNumber numberWithUnsignedInt: _remoteProxies->nodeCount];
[d setObject: o forKey: NSConnectionProxyCount]; [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); M_UNLOCK(_refGate);
@ -1214,7 +1259,16 @@ static NSLock *global_proxies_gate;
DESTROY(_requestQueue); DESTROY(_requestQueue);
if (_replyMap != 0) 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; _replyMap = 0;
} }
@ -1234,6 +1288,11 @@ static NSLock *global_proxies_gate;
argFrame: (arglist_t)argframe 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. */ /* The callback for encoding the args of the method call. */
void encoder (int argnum, void *datum, const char *type, int flags) void encoder (int argnum, void *datum, const char *type, int flags)
@ -1257,11 +1316,6 @@ static NSLock *global_proxies_gate;
} }
/* Encode the method on an RMC, and send it. */ /* 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);
@ -1274,17 +1328,18 @@ static NSLock *global_proxies_gate;
#else #else
type = sel_get_type(sel); type = sel_get_type(sel);
#endif #endif
if (type == 0 || *type == '\0') { if (type == 0 || *type == '\0')
{
type = [[object methodSignatureForSelector: sel] methodType]; type = [[object methodSignatureForSelector: sel] methodType];
if (type) { if (type)
{
sel_register_typed_name(sel_get_name(sel), 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: 0 generate: &seq_num reply: YES];
op = [self _makeOutRmc: seq_num];
if (debug_connection > 4) if (debug_connection > 4)
NSLog(@"building packet seq %d", seq_num); NSLog(@"building packet seq %d", seq_num);
@ -1300,14 +1355,48 @@ static NSLock *global_proxies_gate;
type may be a method_type from a remote machine with a type may be a method_type from a remote machine with a
different architecture, and its argframe layout specifiers different architecture, and its argframe layout specifiers
won't be right for this machine! */ won't be right for this machine! */
out_parameters = mframe_dissect_call (argframe, type, encoder); outParams = mframe_dissect_call (argframe, type, encoder);
if (outParams == YES)
{
needsResponse = YES;
}
else
{
int flags;
needsResponse = NO;
flags = objc_get_type_qualifiers(type);
if ((flags & _F_ONEWAY) == 0)
{
needsResponse = YES;
}
else
{
const char *tmptype = objc_skip_type_qualifiers(type);
if (*tmptype != _C_VOID)
{
needsResponse = YES;
}
}
}
[self _sendOutRmc: op type: METHOD_REQUEST]; [self _sendOutRmc: op type: METHOD_REQUEST];
NSDebugMLLog(@"NSConnection", @"Sent message to 0x%x", (gsaddr)self);
if (debug_connection > 1) if (needsResponse == NO)
NSLog(@"Sent message to 0x%x", (gsaddr)self); {
/*
/* Get the reply rmc, and decode it. */ * 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; NSPortCoder *ip = nil;
BOOL is_exception = NO; BOOL is_exception = NO;
@ -1333,11 +1422,11 @@ static NSLock *global_proxies_gate;
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"connection waiting for request was shut down"]; 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]; 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]; [ip decodeValueOfObjCType: @encode(BOOL) at: &is_exception];
if (is_exception) if (is_exception)
{ {
@ -1353,7 +1442,7 @@ static NSLock *global_proxies_gate;
} }
[ip decodeValueOfObjCType: type at: datum]; [ip decodeValueOfObjCType: type at: datum];
/* -decodeValueOfObjCType:at: malloc's new memory /* -decodeValueOfObjCType:at: malloc's new memory
for char*'s. We need to make sure it gets freed eventually for pointers. We need to make sure it gets freed eventually
so we don't have a memory leak. Request here that it be so we don't have a memory leak. Request here that it be
autorelease'ed. Also autorelease created objects. */ autorelease'ed. Also autorelease created objects. */
if ((*type == _C_CHARPTR || *type == _C_PTR) && *(void**)datum != 0) if ((*type == _C_CHARPTR || *type == _C_PTR) && *(void**)datum != 0)
@ -1362,17 +1451,16 @@ static NSLock *global_proxies_gate;
AUTORELEASE(*(id*)datum); 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. /* 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 this is done is in this function DECODER(). IP will be nil
if mframe_build_return() never called DECODER(), i.e. when if mframe_build_return() never called DECODER(), i.e. when
we are just returning (void).*/ we are just returning (void).*/
NSAssert(ip == (id)-1 || ip == nil, NSInternalInconsistencyException); NSAssert(ip == (id)-1 || ip == nil, NSInternalInconsistencyException);
}
return retframe; return retframe;
} }
}
}
- (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target - (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target
{ {
@ -1382,8 +1470,7 @@ static NSLock *global_proxies_gate;
NSParameterAssert(_receivePort); NSParameterAssert(_receivePort);
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
seq_num = [self _newMsgNumber]; op = [self _makeOutRmc: 0 generate: &seq_num reply: YES];
op = [self _makeOutRmc: seq_num];
[op encodeValueOfObjCType: ":" at: &sel]; [op encodeValueOfObjCType: ":" at: &sel];
[op encodeValueOfObjCType: @encode(unsigned) at: &target]; [op encodeValueOfObjCType: @encode(unsigned) at: &target];
[self _sendOutRmc: op type: METHODTYPE_REQUEST]; [self _sendOutRmc: op type: METHODTYPE_REQUEST];
@ -1544,10 +1631,26 @@ static NSLock *global_proxies_gate;
case RETAIN_REPLY: case RETAIN_REPLY:
{ {
int sequence; int sequence;
GSIMapNode node;
[rmc decodeValueOfObjCType: @encode(int) at: &sequence]; [rmc decodeValueOfObjCType: @encode(int) at: &sequence];
M_LOCK(conn->_queueGate); 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); M_UNLOCK(conn->_queueGate);
} }
break; break;
@ -1591,7 +1694,7 @@ static NSLock *global_proxies_gate;
{ {
char *forward_type = 0; char *forward_type = 0;
id op = nil; id op = nil;
int reply_sequence_number; int reply_sno;
void decoder (int argnum, void *datum, const char *type) void decoder (int argnum, void *datum, const char *type)
{ {
@ -1625,7 +1728,7 @@ static NSLock *global_proxies_gate;
back to the remote application! */ back to the remote application! */
if (!_isValid) if (!_isValid)
return; return;
op = [self _makeOutRmc: reply_sequence_number]; op = [self _makeOutRmc: reply_sno generate: 0 reply: NO];
[op encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; [op encodeValueOfObjCType: @encode(BOOL) at: &is_exception];
} }
switch (*type) switch (*type)
@ -1652,7 +1755,7 @@ static NSLock *global_proxies_gate;
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
/* Save this for later */ /* 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 /* Get the types that we're using, so that we know
exactly what qualifiers the forwarder used. exactly what qualifiers the forwarder used.
@ -1681,7 +1784,7 @@ static NSLock *global_proxies_gate;
{ {
NS_DURING NS_DURING
{ {
op = [self _makeOutRmc: reply_sequence_number]; op = [self _makeOutRmc: reply_sno generate: 0 reply: NO];
[op encodeValueOfObjCType: @encode(BOOL) [op encodeValueOfObjCType: @encode(BOOL)
at: &is_exception]; at: &is_exception];
[op encodeBycopyObject: localException]; [op encodeBycopyObject: localException];
@ -1714,7 +1817,7 @@ static NSLock *global_proxies_gate;
[rmc decodeValueOfObjCType: @encode(int) at: &sequence]; [rmc decodeValueOfObjCType: @encode(int) at: &sequence];
[self _doneInRmc: rmc]; [self _doneInRmc: rmc];
op = [self _makeOutRmc: sequence]; op = [self _makeOutRmc: sequence generate: 0 reply: NO];
[op encodeObject: rootObject]; [op encodeObject: rootObject];
[self _sendOutRmc: op type: ROOTPROXY_REPLY]; [self _sendOutRmc: op type: ROOTPROXY_REPLY];
} }
@ -1761,7 +1864,7 @@ static NSLock *global_proxies_gate;
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
[rmc decodeValueOfObjCType: @encode(int) at: &sequence]; [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]; [rmc decodeValueOfObjCType: @encode(typeof(target)) at: &target];
[self _doneInRmc: rmc]; [self _doneInRmc: rmc];
@ -1828,10 +1931,11 @@ static NSLock *global_proxies_gate;
- (void) shutdown - (void) shutdown
{ {
NSPortCoder *op; NSPortCoder *op;
int sno;
NSParameterAssert(_receivePort); NSParameterAssert(_receivePort);
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
op = [self _makeOutRmc: [self _newMsgNumber]]; op = [self _makeOutRmc: 0 generate: &sno reply: NO];
[self _sendOutRmc: op type: CONNECTION_SHUTDOWN]; [self _sendOutRmc: op type: CONNECTION_SHUTDOWN];
} }
@ -1859,7 +1963,7 @@ static NSLock *global_proxies_gate;
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
[rmc decodeValueOfObjCType: @encode(int) at: &sequence]; [rmc decodeValueOfObjCType: @encode(int) at: &sequence];
op = [self _makeOutRmc: sequence]; op = [self _makeOutRmc: sequence generate: 0 reply: NO];
[rmc decodeValueOfObjCType: ":" at: &sel]; [rmc decodeValueOfObjCType: ":" at: &sel];
[rmc decodeValueOfObjCType: @encode(unsigned) at: &target]; [rmc decodeValueOfObjCType: @encode(unsigned) at: &target];
@ -1891,43 +1995,51 @@ static NSLock *global_proxies_gate;
- _getReplyRmc: (int)sn - _getReplyRmc: (int)sn
{ {
NSPortCoder *rmc; NSPortCoder *rmc;
GSIMapNode node;
NSDate *timeout_date = nil; NSDate *timeout_date = nil;
M_LOCK(_queueGate); 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) if (timeout_date == nil)
{ {
timeout_date = [dateClass allocWithZone: NSDefaultMallocZone()];
timeout_date timeout_date
= [dateClass dateWithTimeIntervalSinceNow: _replyTimeout]; = [timeout_date initWithTimeIntervalSinceNow: _replyTimeout];
} }
M_UNLOCK(_queueGate); M_UNLOCK(_queueGate);
if ([runLoopClass runOnceBeforeDate: timeout_date if ([runLoopClass runOnceBeforeDate: timeout_date
forMode: NSConnectionReplyMode] == NO) forMode: NSConnectionReplyMode] == NO)
{ {
[NSException raise: NSPortTimeoutException M_LOCK(_queueGate);
format: @"timed out waiting for reply"]; node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn);
break;
} }
M_LOCK(_queueGate); M_LOCK(_queueGate);
} }
if (rmc != nil) if (node == 0)
{ {
RETAIN(rmc); rmc = nil;
NSMapRemove(_replyMap, (void*)sn); }
else
{
rmc = node->value.obj;
GSIMapRemoveKey(_replyMap, (GSIMapKey)sn);
} }
M_UNLOCK(_queueGate); M_UNLOCK(_queueGate);
return rmc; TEST_RELEASE(timeout_date);
} if (rmc == nil)
- (int) _newMsgNumber
{ {
int n; [NSException raise: NSInternalInconsistencyException
format: @"no reply message available"];
NSParameterAssert (_isValid); }
M_LOCK(sequenceNumberGate); if (rmc == dummyObject)
n = _messageCount++; {
M_UNLOCK(sequenceNumberGate); [NSException raise: NSPortTimeoutException
return n; format: @"timed out waiting for reply"];
}
return rmc;
} }
- (void) _doneInRmc: (NSPortCoder*)c - (void) _doneInRmc: (NSPortCoder*)c
@ -1966,7 +2078,16 @@ static NSLock *global_proxies_gate;
return coder; 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; NSPortCoder *coder;
unsigned count; unsigned count;
@ -1974,6 +2095,24 @@ static NSLock *global_proxies_gate;
NSParameterAssert(_isValid); NSParameterAssert(_isValid);
M_LOCK(_refGate); 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]; count = [_cachedEncoders count];
if (count > 0) if (count > 0)
{ {
@ -1990,7 +2129,7 @@ static NSLock *global_proxies_gate;
coder = [coder initWithReceivePort: _receivePort coder = [coder initWithReceivePort: _receivePort
sendPort: _sendPort sendPort: _sendPort
components: nil]; components: nil];
[coder encodeValueOfObjCType: @encode(int) at: &sequence]; [coder encodeValueOfObjCType: @encode(int) at: &sno];
return coder; return coder;
} }
@ -2033,9 +2172,9 @@ static NSLock *global_proxies_gate;
case METHOD_REQUEST: case METHOD_REQUEST:
case ROOTPROXY_REQUEST: case ROOTPROXY_REQUEST:
case METHODTYPE_REQUEST: case METHODTYPE_REQUEST:
needsReply = YES;
default: default:
raiseException = YES; raiseException = YES;
needsReply = YES;
break; break;
} }
@ -2110,13 +2249,27 @@ static NSLock *global_proxies_gate;
id object = [anObj localForProxy]; id object = [anObj localForProxy];
unsigned target; unsigned target;
GSLocalCounter *counter; GSLocalCounter *counter;
GSIMapNode node;
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
M_LOCK(_proxiesGate); M_LOCK(_proxiesGate);
M_LOCK(global_proxies_gate); 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. * Keep track of local objects accross all connections.
@ -2136,7 +2289,7 @@ static NSLock *global_proxies_gate;
RELEASE(counter); RELEASE(counter);
} }
[anObj setProxyTarget: target]; [anObj setProxyTarget: target];
NSMapInsert(_localTargets, (void*)target, anObj); GSIMapAddPair(_localTargets, (GSIMapKey)target, (GSIMapVal)anObj);
if (debug_connection > 2) if (debug_connection > 2)
NSLog(@"add local object (0x%x) target (0x%x) " NSLog(@"add local object (0x%x) target (0x%x) "
@"to connection (0x%x) (ref %d)", @"to connection (0x%x) (ref %d)",
@ -2147,13 +2300,22 @@ static NSLock *global_proxies_gate;
- (NSDistantObject*) localForObject: (id)object - (NSDistantObject*) localForObject: (id)object
{ {
GSIMapNode node;
NSDistantObject *p; NSDistantObject *p;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
NSParameterAssert(!p || [p connectionForProxy] == self); NSParameterAssert(p == nil || [p connectionForProxy] == self);
return p; return p;
} }
@ -2176,11 +2338,20 @@ static NSLock *global_proxies_gate;
unsigned target; unsigned target;
GSLocalCounter *counter; GSLocalCounter *counter;
unsigned val = 0; unsigned val = 0;
GSIMapNode node;
M_LOCK(global_proxies_gate); M_LOCK(global_proxies_gate);
M_LOCK(_proxiesGate); 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]; 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) if (debug_connection > 2)
NSLog(@"remove local object (0x%x) target (0x%x) " NSLog(@"remove local object (0x%x) target (0x%x) "
@ -2246,9 +2425,9 @@ static NSLock *global_proxies_gate;
{ {
id op; id op;
unsigned i; 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]; [op encodeValueOfObjCType: @encode(unsigned) at: &number];
@ -2284,9 +2463,9 @@ static NSLock *global_proxies_gate;
NSPortCoder *op; NSPortCoder *op;
id ip; id ip;
id result; 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]; [op encodeValueOfObjCType: @encode(typeof(target)) at: &target];
[self _sendOutRmc: op type: PROXY_RETAIN]; [self _sendOutRmc: op type: PROXY_RETAIN];
@ -2311,7 +2490,7 @@ static NSLock *global_proxies_gate;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); M_LOCK(_proxiesGate);
/* This also releases aProxy */ /* This also releases aProxy */
NSMapRemove(_remoteProxies, (void*)target); GSIMapRemoveKey(_remoteProxies, (GSIMapKey)target);
M_UNLOCK(_proxiesGate); M_UNLOCK(_proxiesGate);
/* /*
@ -2324,40 +2503,59 @@ static NSLock *global_proxies_gate;
- (NSDistantObject*) proxyForTarget: (unsigned)target - (NSDistantObject*) proxyForTarget: (unsigned)target
{ {
NSDistantObject *p; NSDistantObject *p;
GSIMapNode node;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
NSParameterAssert(!p || [p connectionForProxy] == self);
return p; return p;
} }
- (void) addProxy: (NSDistantObject*) aProxy - (void) addProxy: (NSDistantObject*) aProxy
{ {
unsigned target = (unsigned int)[aProxy targetForProxy]; unsigned target = (unsigned int)[aProxy targetForProxy];
GSIMapNode node;
NSParameterAssert (_isValid); NSParameterAssert (_isValid);
NSParameterAssert(aProxy->isa == distantObjectClass); NSParameterAssert(aProxy->isa == distantObjectClass);
NSParameterAssert([aProxy connectionForProxy] == self); NSParameterAssert([aProxy connectionForProxy] == self);
M_LOCK(_proxiesGate); M_LOCK(_proxiesGate);
if (NSMapGet(_remoteProxies, (void*)target)) node = GSIMapNodeForKey(_remoteProxies, (GSIMapKey)target);
if (node != 0)
{ {
M_UNLOCK(_proxiesGate); M_UNLOCK(_proxiesGate);
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"Trying to add the same proxy twice"]; format: @"Trying to add the same proxy twice"];
} }
NSMapInsert(_remoteProxies, (void*)target, aProxy); GSIMapAddPair(_remoteProxies, (GSIMapKey)target, (GSIMapVal)aProxy);
M_UNLOCK(_proxiesGate); M_UNLOCK(_proxiesGate);
} }
- (id) includesProxyForTarget: (unsigned)target - (id) includesProxyForTarget: (unsigned)target
{ {
NSDistantObject *ret; NSDistantObject *ret;
GSIMapNode node;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
return ret; return ret;
} }
@ -2365,10 +2563,19 @@ static NSLock *global_proxies_gate;
- (id) includesLocalObject: (id)anObj - (id) includesLocalObject: (id)anObj
{ {
NSDistantObject *ret; NSDistantObject *ret;
GSIMapNode node;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
return ret; return ret;
} }
@ -2376,10 +2583,19 @@ static NSLock *global_proxies_gate;
- (id) includesLocalTarget: (unsigned)target - (id) includesLocalTarget: (unsigned)target
{ {
NSDistantObject *ret; NSDistantObject *ret;
GSIMapNode node;
/* Don't assert (_isValid); */ /* Don't assert (_isValid); */
M_LOCK(_proxiesGate); 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); M_UNLOCK(_proxiesGate);
return ret; return ret;
} }
@ -2900,6 +3116,8 @@ static int messages_received_count;
is_valid = NO; is_valid = NO;
NSHashRemove(connection_table, self);
/* /*
* Don't need notifications any more - so remove self as observer. * Don't need notifications any more - so remove self as observer.
*/ */

View file

@ -271,7 +271,7 @@ enum
*/ */
if ((proxy = [aConnection localForObject: anObject])) if ((proxy = [aConnection localForObject: anObject]))
{ {
return [proxy retain]; return RETAIN(proxy);
} }
proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass, proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass,
@ -291,7 +291,7 @@ enum
*/ */
if ((proxy = [aConnection proxyForTarget: target])) if ((proxy = [aConnection proxyForTarget: target]))
{ {
return [proxy retain]; return RETAIN(proxy);
} }
proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass, proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass,
@ -329,15 +329,15 @@ enum
+ (NSDistantObject*) proxyWithLocal: (id)anObject + (NSDistantObject*) proxyWithLocal: (id)anObject
connection: (NSConnection*)aConnection connection: (NSConnection*)aConnection
{ {
return [[placeHolder initWithLocal: anObject return AUTORELEASE([placeHolder initWithLocal: anObject
connection: aConnection] autorelease]; connection: aConnection]);
} }
+ (NSDistantObject*) proxyWithTarget: (unsigned)anObject + (NSDistantObject*) proxyWithTarget: (unsigned)anObject
connection: (NSConnection*)aConnection connection: (NSConnection*)aConnection
{ {
return [[placeHolder initWithTarget: anObject return AUTORELEASE([placeHolder initWithTarget: anObject
connection: aConnection] autorelease]; connection: aConnection]);
} }
- (NSConnection*) connectionForProxy - (NSConnection*) connectionForProxy
@ -481,7 +481,7 @@ enum
/* /*
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO) if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
{ {
[self release]; RELEASE(self);
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"NSDistantObject objects only decode with " format: @"NSDistantObject objects only decode with "
@"NSPortCoder class"]; @"NSPortCoder class"];
@ -513,7 +513,7 @@ enum
if (![[decoder_connection class] includesLocalTarget: target]) if (![[decoder_connection class] includesLocalTarget: target])
{ {
[self release]; RELEASE(self);
[NSException raise: @"ProxyDecodedBadTarget" [NSException raise: @"ProxyDecodedBadTarget"
format: @"No local object with given target (0x%x)", format: @"No local object with given target (0x%x)",
target]; target];
@ -528,8 +528,8 @@ enum
NSLog(@"Local object is 0x%x (0x%x)\n", NSLog(@"Local object is 0x%x (0x%x)\n",
(gsaddr)o, (gsaddr)o ? o->_object : 0); (gsaddr)o, (gsaddr)o ? o->_object : 0);
} }
[self release]; RELEASE(self);
return o ? [o->_object retain] : nil; return o ? RETAIN(o->_object) : nil;
} }
case PROXY_LOCAL_FOR_SENDER: case PROXY_LOCAL_FOR_SENDER:
@ -545,9 +545,9 @@ enum
if (debug_proxy) if (debug_proxy)
NSLog(@"Receiving a proxy, was local 0x%x connection 0x%x\n", NSLog(@"Receiving a proxy, was local 0x%x connection 0x%x\n",
target, (gsaddr)decoder_connection); target, (gsaddr)decoder_connection);
[self release]; RELEASE(self);
return [[NSDistantObject proxyWithTarget: target return RETAIN([NSDistantObject proxyWithTarget: target
connection: decoder_connection] retain]; connection: decoder_connection]);
case PROXY_REMOTE_FOR_BOTH: case PROXY_REMOTE_FOR_BOTH:
/* /*
@ -627,9 +627,9 @@ enum
if ([proxy_connection includesProxyForTarget: target] == NO) if ([proxy_connection includesProxyForTarget: target] == NO)
[proxy_connection retainTarget: target]; [proxy_connection retainTarget: target];
result = [[NSDistantObject proxyWithTarget: target result = RETAIN([NSDistantObject proxyWithTarget: target
connection: proxy_connection] retain]; connection: proxy_connection]);
[self release]; RELEASE(self);
/* /*
* Finally - we have a proxy via a direct connection to the * Finally - we have a proxy via a direct connection to the
@ -643,7 +643,7 @@ enum
default: default:
/* xxx This should be something different than NSGenericException. */ /* xxx This should be something different than NSGenericException. */
[self release]; RELEASE(self);
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"Bad proxy tag"]; format: @"Bad proxy tag"];
} }
@ -663,8 +663,9 @@ enum
*/ */
if ((new_proxy = [aConnection localForObject: anObject])) if ((new_proxy = [aConnection localForObject: anObject]))
{ {
[self release]; RETAIN(new_proxy);
return [new_proxy retain]; RELEASE(self);
return new_proxy;
} }
/* /*
@ -677,7 +678,7 @@ enum
/* /*
* We register this proxy with the connection using it. * We register this proxy with the connection using it.
*/ */
_connection = [aConnection retain]; _connection = RETAIN(aConnection);
[_connection addLocalObject: self]; [_connection addLocalObject: self];
if (debug_proxy) if (debug_proxy)
@ -699,8 +700,9 @@ enum
*/ */
if ((new_proxy = [aConnection proxyForTarget: target])) if ((new_proxy = [aConnection proxyForTarget: target]))
{ {
[self release]; RETAIN(new_proxy);
return [new_proxy retain]; RELEASE(self);
return new_proxy;
} }
_object = nil; _object = nil;
@ -710,7 +712,7 @@ enum
* We retain our connection so it can't disappear while the app * We retain our connection so it can't disappear while the app
* may want to use it. * may want to use it.
*/ */
_connection = [aConnection retain]; _connection = RETAIN(aConnection);
/* /*
* We register this object with the connection using it. * We register this object with the connection using it.
@ -808,7 +810,7 @@ enum
*/ */
if (_object == nil) if (_object == nil)
[_connection removeProxy: self]; [_connection removeProxy: self];
[_connection release]; RELEASE(_connection);
} }
} }

View file

@ -382,6 +382,8 @@ typedef enum {
return; return;
if (handle == nil) if (handle == nil)
{
if (state == GSPC_LOPEN)
{ {
NSLog(@"Failed to find gdomap port with name '%@',\nperhaps your " NSLog(@"Failed to find gdomap port with name '%@',\nperhaps your "
@"/etc/services file is not correctly set up?\n" @"/etc/services file is not correctly set up?\n"
@ -394,7 +396,8 @@ typedef enum {
} }
NS_HANDLER NS_HANDLER
{ {
NSLog(@"Exception creating handle for gdomap - %@", localException); NSLog(@"Exception creating handle for gdomap - %@",
localException);
[self fail]; [self fail];
} }
NS_ENDHANDLER NS_ENDHANDLER
@ -404,6 +407,11 @@ typedef enum {
serverPort = @"538"; serverPort = @"538";
} }
} }
else
{
[self fail];
}
}
if (state == GSPC_FAIL) if (state == GSPC_FAIL)
return; return;