Added registerName: method to NSConnection with associated changes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@5923 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 2000-02-04 18:14:13 +00:00
parent 78616c9359
commit 1629c565b9
6 changed files with 379 additions and 259 deletions

View file

@ -1,3 +1,10 @@
Fri Feb 4 17:20:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSPortNameServer.m: New methods for use by NSConnection
* Foundation/NSPortNameServer.h: ditto
* Source/NSConnection.m: Tidied a little and added ([-registerName:])
* Source/NSConnection.h: ditto
Sun Jan 16 9:10:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk> Sun Jan 16 9:10:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Moved objc-load.c to objc-load.m and filnd-exec.c to find-exec.m Moved objc-load.c to objc-load.m and filnd-exec.c to find-exec.m

View file

@ -95,6 +95,7 @@ extern NSString *NSConnectionProxyCount; /* Objects received */
- (BOOL) independentConversationQueueing; - (BOOL) independentConversationQueueing;
- (void) invalidate; - (void) invalidate;
- (BOOL) isValid; - (BOOL) isValid;
- (BOOL) registerName: (NSString*)name;
- (NSArray *) remoteObjects; - (NSArray *) remoteObjects;
- (void) removeRequestMode: (NSString*)mode; - (void) removeRequestMode: (NSString*)mode;
- (void) removeRunLoop: (NSRunLoop *)runloop; - (void) removeRunLoop: (NSRunLoop *)runloop;

View file

@ -44,7 +44,9 @@
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
@interface NSPortNameServer (GNUstep) @interface NSPortNameServer (GNUstep)
- (NSArray*) namesForPort: (NSPort*)port; /* return all names for port */
- (void) removePort: (NSPort*)port; /* remove all names for port */ - (void) removePort: (NSPort*)port; /* remove all names for port */
- (void) removePort: (NSPort*)port forName: (NSString*)name;
@end @end
#endif #endif

View file

@ -49,6 +49,7 @@
#include <Foundation/NSThread.h> #include <Foundation/NSThread.h>
#include <Foundation/NSPort.h> #include <Foundation/NSPort.h>
#include <Foundation/NSPortMessage.h> #include <Foundation/NSPortMessage.h>
#include <Foundation/NSPortNameServer.h>
#include <Foundation/NSNotification.h> #include <Foundation/NSNotification.h>
NSString* NSConnectionReplyMode = @"NSConnectionReplyMode"; NSString* NSConnectionReplyMode = @"NSConnectionReplyMode";
@ -264,13 +265,14 @@ static int messages_received_count;
+ (NSConnection*) connectionWithRegisteredName: (NSString*)n + (NSConnection*) connectionWithRegisteredName: (NSString*)n
host: (NSString*)h host: (NSString*)h
{ {
NSDistantObject *proxy; NSDistantObject *proxy;
proxy = [self rootProxyForConnectionWithRegisteredName: n host: h]; proxy = [self rootProxyForConnectionWithRegisteredName: n host: h];
if (proxy) { if (proxy != nil)
return [proxy connectionForProxy]; {
return [proxy connectionForProxy];
} }
return nil; return nil;
} }
/* /*
@ -287,36 +289,38 @@ static int messages_received_count;
d = GSCurrentThreadDictionary(); d = GSCurrentThreadDictionary();
c = (NSConnection*)[d objectForKey: tkey]; c = (NSConnection*)[d objectForKey: tkey];
if (c != nil && [c isValid] == NO) { if (c != nil && [c isValid] == NO)
/* {
* If the default connection for this thread has been invalidated - /*
* release it and create a new one. * If the default connection for this thread has been invalidated -
*/ * release it and create a new one.
[d removeObjectForKey: tkey]; */
c = nil; [d removeObjectForKey: tkey];
} c = nil;
if (c == nil) { }
c = [NSConnection new]; if (c == nil)
[d setObject: c forKey: tkey]; {
RELEASE(c); c = [NSConnection new];
} [d setObject: c forKey: tkey];
RELEASE(c);
}
return c; return c;
} }
+ (void) initialize + (void) initialize
{ {
connection_table = connection_table =
NSCreateHashTable (NSNonRetainedObjectHashCallBacks, 0); NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
connection_table_gate = [NSLock new]; connection_table_gate = [NSLock new];
/* xxx When NSHashTable's are working, change this. */ /* xxx When NSHashTable's are working, change this. */
all_connections_local_objects = all_connections_local_objects =
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0); NSObjectMapValueCallBacks, 0);
all_connections_local_targets = all_connections_local_targets =
NSCreateMapTable (NSIntMapKeyCallBacks, NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0); NSNonOwnedPointerMapValueCallBacks, 0);
all_connections_local_cached = all_connections_local_cached =
NSCreateMapTable (NSIntMapKeyCallBacks, NSCreateMapTable(NSIntMapKeyCallBacks,
NSObjectMapValueCallBacks, 0); NSObjectMapValueCallBacks, 0);
received_request_rmc_queue = [[NSMutableArray alloc] initWithCapacity: 32]; received_request_rmc_queue = [[NSMutableArray alloc] initWithCapacity: 32];
received_request_rmc_queue_gate = [NSLock new]; received_request_rmc_queue_gate = [NSLock new];
@ -337,16 +341,18 @@ static int messages_received_count;
default_request_timeout = CONNECTION_DEFAULT_TIMEOUT; default_request_timeout = CONNECTION_DEFAULT_TIMEOUT;
} }
+ new + (id) new
{ {
id newPort = [[default_receive_port_class newForReceiving] autorelease]; NSPort *newPort;
id newConn = [NSConnection newForInPort: newPort NSConnection *newConn;
outPort: nil
ancestorConnection: nil]; newConn = [self alloc];
newConn = [newConn initWithReceivePort: newPort sendPort: nil];
RELEASE(newPort);
return newConn; return newConn;
} }
+ (id)currentConversation + (id) currentConversation
{ {
[self notImplemented: _cmd]; [self notImplemented: _cmd];
return self; return self;
@ -355,38 +361,43 @@ static int messages_received_count;
+ (NSDistantObject*) rootProxyForConnectionWithRegisteredName: (NSString*)n + (NSDistantObject*) rootProxyForConnectionWithRegisteredName: (NSString*)n
host: (NSString*)h host: (NSString*)h
{ {
id p = [default_send_port_class newForSendingToRegisteredName: n onHost: h]; id p = [default_send_port_class newForSendingToRegisteredName: n onHost: h];
if (p == nil) { if (p == nil)
return nil; {
return nil;
} }
return [self rootProxyAtPort: [p autorelease]]; return [self rootProxyAtPort: [p autorelease]];
} }
+ (void) _timeout: (NSTimer*)t + (void) _timeout: (NSTimer*)t
{ {
NSArray *cached_locals; NSArray *cached_locals;
int i; int i;
cached_locals = NSAllMapTableValues(all_connections_local_cached); cached_locals = NSAllMapTableValues(all_connections_local_cached);
for (i = [cached_locals count]; i > 0; i--) { for (i = [cached_locals count]; i > 0; i--)
CachedLocalObject *item = [cached_locals objectAtIndex: i-1]; {
CachedLocalObject *item = [cached_locals objectAtIndex: i-1];
if ([item countdown] == NO) { if ([item countdown] == NO)
GSLocalCounter *counter = [item obj]; {
NSMapRemove(all_connections_local_cached, (void*)counter->target); GSLocalCounter *counter = [item obj];
NSMapRemove(all_connections_local_cached, (void*)counter->target);
} }
} }
if ([cached_locals count] == 0) { if ([cached_locals count] == 0)
[t invalidate]; {
timer = nil; [t invalidate];
timer = nil;
} }
} }
- (void) addRequestMode: (NSString*)mode - (void) addRequestMode: (NSString*)mode
{ {
if (![request_modes containsObject: mode]) { if ([request_modes containsObject: mode] == NO)
[request_modes addObject: mode]; {
[[NSRunLoop currentRunLoop] addPort: receive_port forMode: mode]; [request_modes addObject: mode];
[[NSRunLoop currentRunLoop] addPort: receive_port forMode: mode];
} }
} }
@ -431,12 +442,12 @@ static int messages_received_count;
- (id) init - (id) init
{ {
id newPort = [[default_receive_port_class newForReceiving] autorelease]; NSPort *newPort;
id newConn = [NSConnection newForInPort: newPort
outPort: nil newPort = [default_receive_port_class newForReceiving];
ancestorConnection: nil]; self = [self initWithReceivePort: newPort sendPort: nil];
[self release]; RELEASE(newPort);
return newConn; return self;
} }
/* /*
@ -516,6 +527,33 @@ static int messages_received_count;
return is_valid; return is_valid;
} }
- (BOOL) registerName: (NSString*)name
{
NSPortNameServer *svr = [NSPortNameServer defaultPortNameServer];
NSArray *names = [svr namesForPort: receive_port];
BOOL result = YES;
if (name != nil)
{
result = [svr registerPort: receive_port forName: name];
}
if (result == YES && [names count] > 0)
{
unsigned i;
for (i = 0; i < [names count]; i++)
{
NSString *tmp = [names objectAtIndex: i];
if ([tmp isEqualToString: name] == NO)
{
[svr removePort: receive_port forName: name];
}
}
}
return result;
}
- (void) release - (void) release
{ {
/* /*
@ -676,7 +714,7 @@ static int messages_received_count;
- (void) gcFinalize - (void) gcFinalize
{ {
NSAutoreleasePool *arp = [NSAutoreleasePool new]; CREATE_AUTORELEASE_POOL(arp);
if (debug_connection) if (debug_connection)
NSLog(@"finalising 0x%x\n", (gsaddr)self); NSLog(@"finalising 0x%x\n", (gsaddr)self);
@ -690,26 +728,35 @@ static int messages_received_count;
/* Remove rootObject from root_object_dictionary /* Remove rootObject from root_object_dictionary
if this is last connection */ if this is last connection */
if (![NSConnection connectionsCountWithInPort: receive_port]) if (receive_port != nil
[NSConnection setRootObject: nil forInPort: receive_port]; && [NSConnection connectionsCountWithInPort: receive_port] == 0)
{
[NSConnection setRootObject: nil forInPort: receive_port];
}
/* Remove receive port from run loop. */ /* Remove receive port from run loop. */
[self setRequestMode: nil]; [self setRequestMode: nil];
[[NSRunLoop currentRunLoop] removePort: receive_port if (receive_port != nil)
forMode: NSConnectionReplyMode]; {
[request_modes release]; [[NSRunLoop currentRunLoop] removePort: receive_port
forMode: NSConnectionReplyMode];
}
RELEASE(request_modes);
/* Finished with ports - releasing them may generate a notification */ /* Finished with ports - releasing them may generate a notification */
[receive_port release]; RELEASE(receive_port);
[send_port release]; RELEASE(send_port);
[proxiesHashGate lock]; [proxiesHashGate lock];
NSFreeMapTable (remote_proxies); if (remote_proxies != 0)
NSFreeMapTable (local_objects); NSFreeMapTable(remote_proxies);
NSFreeMapTable (local_targets); if (local_objects != 0)
NSFreeMapTable(local_objects);
if (local_targets != 0)
NSFreeMapTable(local_targets);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
[arp release]; RELEASE(arp);
} }
/* Getting and setting class variables */ /* Getting and setting class variables */
@ -817,7 +864,7 @@ static int messages_received_count;
newPort = [[default_receive_port_class newForReceiving] autorelease]; newPort = [[default_receive_port_class newForReceiving] autorelease];
newConn = [self newForInPort: newPort outPort: nil newConn = [self newForInPort: newPort outPort: nil
ancestorConnection: nil]; ancestorConnection: nil];
[self setRootObject: anObj forInPort: newPort]; [[self class] setRootObject: anObj forInPort: newPort];
return newConn; return newConn;
} }
@ -842,12 +889,15 @@ static int messages_received_count;
id newPort; id newPort;
id newConn; id newConn;
newPort = [default_receive_port_class newForReceivingFromRegisteredName: n newPort = [default_receive_port_class newForReceiving];
fromPort: p]; newConn = [self alloc];
newConn = [self newForInPort: [newPort autorelease] newConn = [newConn initWithReceivePort: newPort sendPort: nil];
outPort: nil RELEASE(newPort);
ancestorConnection: nil]; [newConn setRootObject: anObj];
[self setRootObject: anObj forInPort: newPort]; if ([newConn registerName: n] == NO)
{
DESTROY(newConn);
}
return newConn; return newConn;
} }
@ -889,163 +939,15 @@ static int messages_received_count;
} }
/* This is the designated initializer for NSConnection */
+ (NSConnection*) newForInPort: (NSPort*)ip + (NSConnection*) newForInPort: (NSPort*)ip
outPort: (NSPort*)op outPort: (NSPort*)op
ancestorConnection: (NSConnection*)ancestor ancestorConnection: (NSConnection*)ancestor
{ {
NSNotificationCenter *nCenter; NSConnection *conn;
NSConnection *newConn;
NSParameterAssert (ip); conn = [self alloc];
conn = [conn initWithReceivePort: ip sendPort: op];
/* Find previously existing connection if there */ return conn;
newConn = [self connectionByInPort: ip outPort: op];
if (newConn)
{
if (debug_connection > 2)
NSLog(@"Found existing connection (0x%x) for \n\t%@\n\t%@\n",
(gsaddr)newConn, [ip description], [op description]);
return [newConn retain];
}
[connection_table_gate lock];
newConn = [[NSConnection alloc] _superInit];
if (debug_connection)
NSLog(@"Created new connection 0x%x\n\t%@\n\t%@\n",
(gsaddr)newConn, [ip description], [op description]);
newConn->is_valid = YES;
newConn->receive_port = ip;
[ip retain];
newConn->send_port = op;
[op retain];
newConn->message_count = 0;
newConn->rep_out_count = 0;
newConn->req_out_count = 0;
newConn->rep_in_count = 0;
newConn->req_in_count = 0;
/* 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. */
newConn->local_objects =
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
/* This maps handles for local objects to their local proxies. */
newConn->local_targets =
NSCreateMapTable (NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
/* This maps [proxy targetForProxy] to proxy. The proxy's are retained. */
newConn->remote_proxies =
NSCreateMapTable (NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
newConn->reply_timeout = [self defaultInTimeout];
newConn->request_timeout = [self defaultOutTimeout];
newConn->encoding_class = default_encoding_class;
/* xxx ANCESTOR argument is currently ignored; in the future it
will be removed. */
/* xxx It this the correct behavior? */
if (!(ancestor = NSMapGet (receive_port_2_ancestor, ip)))
{
NSMapInsert (receive_port_2_ancestor, ip, newConn);
/* This will cause the connection with the registered name
to receive the -invokeWithObject: from the IN_PORT.
This ends up being the ancestor of future new NSConnections
on this in port. */
/* xxx Could it happen that this connection was invalidated, but
the others would still be OK? That would cause problems.
No. I don't think that can happen. */
[(InPort*)ip setReceivedPacketInvocation: (id)[self class]];
}
if (ancestor)
{
newConn->receive_port_class = [ancestor receivePortClass];
newConn->send_port_class = [ancestor sendPortClass];
}
else
{
newConn->receive_port_class = default_receive_port_class;
newConn->send_port_class = default_send_port_class;
}
newConn->independent_queueing = NO;
newConn->reply_depth = 0;
newConn->delegate = nil;
/*
* Set up request modes array and make sure the receiving port is
* added to the run loop to get data.
*/
newConn->request_modes = [[NSMutableArray arrayWithObject:
NSDefaultRunLoopMode] retain];
[[NSRunLoop currentRunLoop] addPort: (NSPort*)ip
forMode: NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addPort: (NSPort*)ip
forMode: NSConnectionReplyMode];
/* Ssk the delegate for permission, (OpenStep-style and GNUstep-style). */
/* Preferred OpenStep version, which just allows the returning of BOOL */
if ([[ancestor delegate] respondsTo: @selector(connection: shouldMakeNewConnection: )])
{
if (![[ancestor delegate] connection: ancestor
shouldMakeNewConnection: (NSConnection*)newConn])
{
[connection_table_gate unlock];
[newConn release];
return nil;
}
}
/* Deprecated OpenStep version, which just allows the returning of BOOL */
if ([[ancestor delegate] respondsTo: @selector(makeNewConnection: sender: )])
{
if (![[ancestor delegate] makeNewConnection: (NSConnection*)newConn
sender: ancestor])
{
[connection_table_gate unlock];
[newConn release];
return nil;
}
}
/* Here is the GNUstep version, which allows the delegate to specify
a substitute. Note: The delegate is responsible for freeing
newConn if it returns something different. */
if ([[ancestor delegate] respondsTo: @selector(connection: didConnect: )])
newConn = [[ancestor delegate] connection: ancestor
didConnect: newConn];
/* Register ourselves for invalidation notification when the
ports become invalid. */
nCenter = [NSNotificationCenter defaultCenter];
[nCenter addObserver: newConn
selector: @selector(portIsInvalid: )
name: NSPortDidBecomeInvalidNotification
object: ip];
if (op)
[nCenter addObserver: newConn
selector: @selector(portIsInvalid: )
name: NSPortDidBecomeInvalidNotification
object: op];
/* if OP is nil, making this notification request would have
registered us to receive all NSPortDidBecomeInvalidNotification
requests, independent of which port posted them. This isn't
what we want. */
/* In order that connections may be deallocated - there is an
implementation of [-release] to automatically remove the connection
from this array when it is the only thing retaining it. */
NSHashInsert(connection_table, (void*)newConn);
[connection_table_gate unlock];
[[NSNotificationCenter defaultCenter]
postNotificationName: NSConnectionDidInitializeNotification
object: newConn];
return newConn;
} }
+ (NSConnection*) connectionByInPort: (NSPort*)ip + (NSConnection*) connectionByInPort: (NSPort*)ip
@ -2068,24 +1970,24 @@ static int messages_received_count;
[self _release_targets: &target count: 1]; [self _release_targets: &target count: 1];
} }
- (NSArray *) localObjects - (NSArray*) localObjects
{ {
id c; NSArray *c;
/* Don't assert (is_valid); */ /* Don't assert (is_valid); */
[proxiesHashGate lock]; [proxiesHashGate lock];
c = NSAllMapTableValues (local_objects); c = NSAllMapTableValues(local_objects);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
return c; return c;
} }
- (NSArray *) proxies - (NSArray*) proxies
{ {
id c; NSArray *c;
/* Don't assert (is_valid); */ /* Don't assert (is_valid); */
[proxiesHashGate lock]; [proxiesHashGate lock];
c = NSAllMapTableValues (remote_proxies); c = NSAllMapTableValues(remote_proxies);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
return c; return c;
} }
@ -2270,21 +2172,23 @@ static int messages_received_count;
*/ */
- (void) portIsInvalid: notification - (void) portIsInvalid: notification
{ {
if (is_valid) { if (is_valid)
id port = [notification object]; {
id port = [notification object];
if (debug_connection) if (debug_connection)
NSLog(@"Received port invalidation notification for " {
@"connection 0x%x\n\t%@\n", (gsaddr)self, NSLog(@"Received port invalidation notification for "
[port description]); @"connection 0x%x\n\t%@\n", (gsaddr)self, port);
}
/* We shouldn't be getting any port invalidation notifications, /* We shouldn't be getting any port invalidation notifications,
except from our own ports; this is how we registered ourselves except from our own ports; this is how we registered ourselves
with the NSNotificationCenter in with the NSNotificationCenter in
+newForInPort: outPort: ancestorConnection. */ +newForInPort: outPort: ancestorConnection. */
NSParameterAssert (port == receive_port || port == send_port); NSParameterAssert (port == receive_port || port == send_port);
[self invalidate]; [self invalidate];
} }
} }
@ -2297,32 +2201,188 @@ static int messages_received_count;
+ (NSConnection*) connectionWithReceivePort: (NSPort*)r + (NSConnection*) connectionWithReceivePort: (NSPort*)r
sendPort: (NSPort*)s sendPort: (NSPort*)s
{ {
NSConnection *c; NSConnection *c;
c = [self newForInPort: r outPort: s ancestorConnection: nil]; c = [self alloc];
return [c autorelease]; c = [self initWithReceivePort: r sendPort: s];
return AUTORELEASE(c);
} }
- initWithReceivePort: (NSPort*)r /* This is the designated initializer for NSConnection */
sendPort: (NSPort*)s - (id) initWithReceivePort: (NSPort*)r
sendPort: (NSPort*)s
{ {
[self dealloc]; NSNotificationCenter *nCenter;
return [NSConnection newForInPort: r outPort: s ancestorConnection: nil]; NSConnection *conn;
id del;
NSParameterAssert(r);
/*
* Find previously existing connection if there
*/
conn = [NSConnection connectionByInPort: r outPort: s];
if (conn != nil)
{
if (debug_connection > 2)
{
NSLog(@"Found existing connection (0x%x) for \n\t%@\n\t%@\n",
(gsaddr)conn, r, s);
}
RELEASE(self);
return RETAIN(conn);
}
[connection_table_gate lock];
if (debug_connection)
{
NSLog(@"Initialised new connection 0x%x\n\t%@\n\t%@\n",
(gsaddr)self, r, s);
}
is_valid = YES;
receive_port = RETAIN(r);
send_port = RETAIN(s);
message_count = 0;
rep_out_count = 0;
req_out_count = 0;
rep_in_count = 0;
req_in_count = 0;
/*
* 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.
*/
local_objects =
NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
/*
* This maps handles for local objects to their local proxies.
*/
local_targets =
NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
/*
* This maps [proxy targetForProxy] to proxy. The proxy's are retained.
*/
remote_proxies =
NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
reply_timeout = default_reply_timeout;
request_timeout = default_request_timeout;
encoding_class = default_encoding_class;
/* xxx It this the correct behavior? */
if ((conn = NSMapGet(receive_port_2_ancestor, r)) == nil)
{
NSMapInsert(receive_port_2_ancestor, r, self);
/*
* This will cause the connection with the registered name
* to receive the -invokeWithObject: from the IN_PORT.
* This ends up being the ancestor of future new NSConnections
* on this in port.
*/
/* xxx Could it happen that this connection was invalidated, but
the others would still be OK? That would cause problems.
No. I don't think that can happen. */
[(InPort*)r setReceivedPacketInvocation: (id)[self class]];
}
if (conn != nil)
{
receive_port_class = [conn receivePortClass];
send_port_class = [conn sendPortClass];
}
else
{
receive_port_class = default_receive_port_class;
send_port_class = default_send_port_class;
}
independent_queueing = NO;
reply_depth = 0;
delegate = nil;
/*
* Set up request modes array and make sure the receiving port is
* added to the run loop to get data.
*/
request_modes
= RETAIN([NSMutableArray arrayWithObject: NSDefaultRunLoopMode]);
[[NSRunLoop currentRunLoop] addPort: (NSPort*)r
forMode: NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addPort: (NSPort*)r
forMode: NSConnectionReplyMode];
/* Ask the delegate for permission, (OpenStep-style and GNUstep-style). */
/* Preferred OpenStep version, which just allows the returning of BOOL */
del = [conn delegate];
if ([del respondsTo: @selector(connection:shouldMakeNewConnection:)])
{
if ([del connection: conn shouldMakeNewConnection: self] == NO)
{
[connection_table_gate unlock];
RELEASE(self);
return nil;
}
}
/* Deprecated OpenStep version, which just allows the returning of BOOL */
if ([del respondsTo: @selector(makeNewConnection:sender:)])
{
if (![del makeNewConnection: self sender: conn])
{
[connection_table_gate unlock];
RELEASE(self);
return nil;
}
}
/* Here is the GNUstep version, which allows the delegate to specify
a substitute. Note: The delegate is responsible for freeing
newConn if it returns something different. */
if ([del respondsTo: @selector(connection:didConnect:)])
self = [del connection: conn didConnect: self];
/* Register ourselves for invalidation notification when the
ports become invalid. */
nCenter = [NSNotificationCenter defaultCenter];
[nCenter addObserver: self
selector: @selector(portIsInvalid:)
name: NSPortDidBecomeInvalidNotification
object: r];
if (s != nil)
[nCenter addObserver: self
selector: @selector(portIsInvalid:)
name: NSPortDidBecomeInvalidNotification
object: s];
/* In order that connections may be deallocated - there is an
implementation of [-release] to automatically remove the connection
from this array when it is the only thing retaining it. */
NSHashInsert(connection_table, (void*)self);
[connection_table_gate unlock];
[[NSNotificationCenter defaultCenter]
postNotificationName: NSConnectionDidInitializeNotification
object: self];
return self;
} }
- (NSPort*) receivePort - (NSPort*) receivePort
{ {
return receive_port; return receive_port;
} }
- (void) runInNewThread - (void) runInNewThread
{ {
[self notImplemented: _cmd]; [self notImplemented: _cmd];
} }
- (NSPort*) sendPort - (NSPort*) sendPort
{ {
return send_port; return send_port;
} }
@end @end

View file

@ -558,7 +558,7 @@ typedef enum {
unsigned portNum = 0; unsigned portNum = 0;
unsigned len; unsigned len;
NSMutableArray *array; NSMutableArray *array;
NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: timeout]; NSDate *limit;
if (name == nil) if (name == nil)
{ {
@ -579,6 +579,8 @@ typedef enum {
GDO_NAME_MAX_LEN]; GDO_NAME_MAX_LEN];
} }
limit = [NSDate dateWithTimeIntervalSinceNow: timeout];
/* /*
* get one or more host addresses in network byte order. * get one or more host addresses in network byte order.
*/ */
@ -626,7 +628,7 @@ typedef enum {
if (numSvrs == 0) if (numSvrs == 0)
{ {
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"failed to get list of name servers on net"]; format: @"failed to get list of name servers"];
} }
tmp = com; tmp = com;
com = nil; com = nil;
@ -715,7 +717,8 @@ typedef enum {
[com close]; [com close];
if ([com state] == GSPC_DONE) if ([com state] == GSPC_DONE)
{ {
portNum = GSSwapBigI32ToHost(*(gsu32*)[[com data] bytes]); portNum
= GSSwapBigI32ToHost(*(gsu32*)[[com data] bytes]);
if (portNum != 0) if (portNum != 0)
{ {
singleServer = [com addr]; singleServer = [com addr];
@ -787,7 +790,7 @@ typedef enum {
NSRunLoop *loop = [NSRunLoop currentRunLoop]; NSRunLoop *loop = [NSRunLoop currentRunLoop];
GSPortCom *com; GSPortCom *com;
unsigned len; unsigned len;
NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: timeout]; NSDate *limit;
if (name == nil) if (name == nil)
{ {
@ -811,6 +814,8 @@ typedef enum {
format: @"name of port is too long (max %d) bytes", format: @"name of port is too long (max %d) bytes",
GDO_NAME_MAX_LEN]; GDO_NAME_MAX_LEN];
} }
limit = [NSDate dateWithTimeIntervalSinceNow: timeout];
/* /*
* Lock out other threads while doing I/O to gdomap * Lock out other threads while doing I/O to gdomap
*/ */
@ -1013,6 +1018,27 @@ typedef enum {
@implementation NSPortNameServer (GNUstep) @implementation NSPortNameServer (GNUstep)
/*
* Return the names under which the port is currently registered.
*/
- (NSArray*) namesForPort: (NSPort*)port
{
NSArray *names;
if (port == nil)
{
[NSException raise: NSInvalidArgumentException
format: @"attempt to get names for nil port"];
}
/*
* Lock out other threads while grabbing port names.
*/
[serverLock lock];
names = [(NSSet*)NSMapGet(_portMap, port) allObjects];
[serverLock unlock];
return names;
}
/* /*
* Remove all names for a particular port - used when a port is * Remove all names for a particular port - used when a port is
* invalidated. * invalidated.
@ -1023,7 +1049,7 @@ typedef enum {
NS_DURING NS_DURING
{ {
NSMutableSet *known = (NSMutableSet*)NSMapGet(_portMap, port); NSMutableSet *known = (NSMutableSet*)NSMapGet(_portMap, port);
NSString *name; NSString *name;
while ((name = [known anyObject]) != nil) while ((name = [known anyObject]) != nil)
{ {
@ -1036,7 +1062,31 @@ typedef enum {
[localException raise]; [localException raise];
} }
NS_ENDHANDLER NS_ENDHANDLER
[serverLock unlock];
}
/*
* Remove name for port iff it is registered.
*/
- (void) removePort: (NSPort*)port forName: (NSString*)name
{
[serverLock lock]; [serverLock lock];
NS_DURING
{
NSMutableSet *known = (NSMutableSet*)NSMapGet(_portMap, port);
if ([known member: name] != nil)
{
[self removePortForName: name];
}
}
NS_HANDLER
{
[serverLock unlock];
[localException raise];
}
NS_ENDHANDLER
[serverLock unlock];
} }
@end @end

View file

@ -222,7 +222,7 @@ static Class NSMutableSet_concrete_class;
} }
/* Same as NSArray */ /* Same as NSArray */
- initWithObjects: firstObject, ... - (id) initWithObjects: firstObject, ...
{ {
va_list ap; va_list ap;
va_start(ap, firstObject); va_start(ap, firstObject);
@ -232,12 +232,12 @@ static Class NSMutableSet_concrete_class;
} }
/* Override superclass's designated initializer */ /* Override superclass's designated initializer */
- init - (id) init
{ {
return [self initWithObjects: NULL count: 0]; return [self initWithObjects: NULL count: 0];
} }
- initWithArray: (NSArray*)other - (id) initWithArray: (NSArray*)other
{ {
unsigned count = [other count]; unsigned count = [other count];