mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Some tidyup and improvements of new DO performance etc.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6866 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a8432b33bc
commit
5fa248bac4
10 changed files with 503 additions and 202 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2000-07-04 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSConnection.m: Improved coder caching and added code for
|
||||
multiple thread support.
|
||||
* Source/GSPortCoder.m: Improved performance of class version
|
||||
lookup and tidied.
|
||||
* Source/GSTcpPort.m: Ensure we don't remain in the run loop any
|
||||
longer than necessary.
|
||||
* Source/NSArchiver.m: minor tidyup
|
||||
* Source/NSDistantObject.m: minor performance tweak
|
||||
* Source/NSUnarchiver.m: minor tidyup.
|
||||
|
||||
2000-07-03 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSConnection.m: Cache coders fro performance.
|
||||
|
|
|
@ -63,6 +63,7 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */
|
|||
BOOL _independentQueueing;
|
||||
BOOL _authenticateIn;
|
||||
BOOL _authenticateOut;
|
||||
BOOL _multipleThreads;
|
||||
NSPort *_receivePort;
|
||||
NSPort *_sendPort;
|
||||
unsigned _requestDepth;
|
||||
|
@ -82,8 +83,8 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */
|
|||
NSMutableArray *_requestQueue;
|
||||
id _delegate;
|
||||
NSRecursiveLock *_refGate;
|
||||
NSPortCoder *_cachedDecoder;
|
||||
NSPortCoder *_cachedEncoder;
|
||||
NSMutableArray *_cachedDecoders;
|
||||
NSMutableArray *_cachedEncoders;
|
||||
}
|
||||
|
||||
+ (NSArray*) allConnections;
|
||||
|
@ -142,6 +143,9 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */
|
|||
*/
|
||||
@interface NSConnection (GNUstepExtensions) <GCFinalization>
|
||||
|
||||
+ (NSConnection*) newRegisteringAtName: (NSString*)n
|
||||
withRootObject: (id)anObject;
|
||||
|
||||
- (void) gcFinalize;
|
||||
|
||||
- (retval_t) forwardForProxy: (NSDistantObject*)object
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
#ifndef _IN_PORT_CODER_M
|
||||
#undef GSIArray
|
||||
#endif
|
||||
NSMutableArray *_cInfo; /* Class version information. */
|
||||
NSMutableDictionary *_cInfo; /* Class version information. */
|
||||
unsigned _cursor; /* Position in data buffer. */
|
||||
unsigned _version; /* Version of archiver used. */
|
||||
NSZone *_zone; /* Zone for allocating objs. */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
@interface NSArchiver : NSCoder
|
||||
{
|
||||
@private
|
||||
NSMutableData *_data; /* Data to write into. */
|
||||
id _dst; /* Serialization destination. */
|
||||
IMP _serImp; /* Method to serialize with. */
|
||||
|
@ -137,6 +138,7 @@
|
|||
|
||||
@interface NSUnarchiver : NSCoder
|
||||
{
|
||||
@private
|
||||
NSData *data; /* Data to write into. */
|
||||
Class dataClass; /* What sort of data is it? */
|
||||
id src; /* Deserialization source. */
|
||||
|
|
|
@ -56,6 +56,12 @@
|
|||
#define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
||||
#define M_UNLOCK(X) {NSDebugMLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
|
||||
|
||||
static Class connectionClass;
|
||||
static Class dateClass;
|
||||
static Class distantObjectClass;
|
||||
static Class portCoderClass;
|
||||
static Class runLoopClass;
|
||||
|
||||
static NSString*
|
||||
stringFromMsgType(int type)
|
||||
{
|
||||
|
@ -121,14 +127,14 @@ stringFromMsgType(int type)
|
|||
unsigned target;
|
||||
id object;
|
||||
}
|
||||
+ (GSLocalCounter*) newWithObject: (id)ob;
|
||||
+ (id) newWithObject: (id)ob;
|
||||
@end
|
||||
|
||||
@implementation GSLocalCounter
|
||||
|
||||
static unsigned local_object_counter = 0;
|
||||
|
||||
+ (GSLocalCounter*) newWithObject: (id)obj
|
||||
+ (id) newWithObject: (id)obj
|
||||
{
|
||||
GSLocalCounter *counter;
|
||||
|
||||
|
@ -141,7 +147,7 @@ static unsigned local_object_counter = 0;
|
|||
- (void) dealloc
|
||||
{
|
||||
RELEASE(object);
|
||||
[super dealloc];
|
||||
NSDeallocateObject(self);
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -161,24 +167,25 @@ static unsigned local_object_counter = 0;
|
|||
}
|
||||
- (BOOL)countdown;
|
||||
- (id) obj;
|
||||
+ (CachedLocalObject*) itemWithObject: (id)o time: (int)t;
|
||||
+ (id) newWithObject: (id)o time: (int)t;
|
||||
@end
|
||||
|
||||
@implementation CachedLocalObject
|
||||
|
||||
+ (CachedLocalObject*) itemWithObject: (id)o time: (int)t
|
||||
+ (id) newWithObject: (id)o time: (int)t
|
||||
{
|
||||
CachedLocalObject *item = [[self alloc] init];
|
||||
CachedLocalObject *item;
|
||||
|
||||
item = (CachedLocalObject*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
item->obj = RETAIN(o);
|
||||
item->time = t;
|
||||
return AUTORELEASE(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(obj);
|
||||
[super dealloc];
|
||||
NSDeallocateObject(self);
|
||||
}
|
||||
|
||||
- (BOOL) countdown
|
||||
|
@ -198,11 +205,12 @@ static unsigned local_object_counter = 0;
|
|||
|
||||
|
||||
@interface NSConnection (Private)
|
||||
+ (void) setDebug: (int)val;
|
||||
- (void) handlePortMessage: (NSPortMessage*)msg;
|
||||
- (void) _runInNewThread;
|
||||
+ (void) setDebug: (int)val;
|
||||
|
||||
- _getReplyRmc: (int)n;
|
||||
- (void) _doneInRmc: (NSPortCoder*)c;
|
||||
- (NSPortCoder*) _getReplyRmc: (int)sn;
|
||||
- (NSPortCoder*) _makeInRmc: (NSMutableArray*)components;
|
||||
- (NSPortCoder*) _makeOutRmc: (int)sequence;
|
||||
- (int) _newMsgNumber;
|
||||
|
@ -300,14 +308,6 @@ static NSMapTable *all_connections_local_targets = NULL;
|
|||
static NSMapTable *all_connections_local_cached = NULL;
|
||||
static NSLock *global_proxies_gate;
|
||||
|
||||
/* rmc handling */
|
||||
static NSMutableArray *received_request_rmc_queue;
|
||||
static NSLock *received_request_rmc_queue_gate;
|
||||
static NSMutableArray *received_reply_rmc_queue;
|
||||
static NSLock *received_reply_rmc_queue_gate;
|
||||
|
||||
static int messages_received_count;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -413,29 +413,33 @@ static int messages_received_count;
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
connection_table =
|
||||
NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
|
||||
connection_table_gate = [NSLock new];
|
||||
/* xxx When NSHashTable's are working, change this. */
|
||||
all_connections_local_objects =
|
||||
NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
all_connections_local_targets =
|
||||
NSCreateMapTable(NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
all_connections_local_cached =
|
||||
NSCreateMapTable(NSIntMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
global_proxies_gate = [NSLock new];
|
||||
received_request_rmc_queue = [[NSMutableArray alloc] initWithCapacity: 32];
|
||||
received_request_rmc_queue_gate = [NSLock new];
|
||||
received_reply_rmc_queue = [[NSMutableArray alloc] initWithCapacity: 32];
|
||||
received_reply_rmc_queue_gate = [NSLock new];
|
||||
root_object_map =
|
||||
NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
root_object_map_gate = [NSLock new];
|
||||
messages_received_count = 0;
|
||||
if (self == [NSConnection class])
|
||||
{
|
||||
connectionClass = self;
|
||||
dateClass = [NSDate class];
|
||||
distantObjectClass = [NSDistantObject class];
|
||||
portCoderClass = [NSPortCoder class];
|
||||
runLoopClass = [NSRunLoop class];
|
||||
|
||||
connection_table =
|
||||
NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
|
||||
connection_table_gate = [NSLock new];
|
||||
/* xxx When NSHashTable's are working, change this. */
|
||||
all_connections_local_objects =
|
||||
NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
all_connections_local_targets =
|
||||
NSCreateMapTable(NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
all_connections_local_cached =
|
||||
NSCreateMapTable(NSIntMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
global_proxies_gate = [NSLock new];
|
||||
root_object_map =
|
||||
NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
root_object_map_gate = [NSLock new];
|
||||
}
|
||||
}
|
||||
|
||||
+ (id) new
|
||||
|
@ -558,7 +562,7 @@ static int messages_received_count;
|
|||
|
||||
- (void) enableMultipleThreads
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
_multipleThreads = YES;
|
||||
}
|
||||
|
||||
- (BOOL) independentConversationQueueing
|
||||
|
@ -573,7 +577,7 @@ static int messages_received_count;
|
|||
* -init returns the default connection.
|
||||
*/
|
||||
RELEASE(self);
|
||||
return RETAIN([NSConnection defaultConnection]);
|
||||
return RETAIN([connectionClass defaultConnection]);
|
||||
}
|
||||
|
||||
/* This is the designated initializer for NSConnection */
|
||||
|
@ -649,6 +653,12 @@ static int messages_received_count;
|
|||
_repInCount = 0;
|
||||
_reqInCount = 0;
|
||||
|
||||
/*
|
||||
* These arrays cache NSPortCoder objects
|
||||
*/
|
||||
_cachedDecoders = [NSMutableArray new];
|
||||
_cachedEncoders = [NSMutableArray new];
|
||||
|
||||
/*
|
||||
* This is used to queue up incoming NSPortMessages representing requests
|
||||
* that can't immediately be dealt with.
|
||||
|
@ -710,7 +720,7 @@ static int messages_received_count;
|
|||
* Set up request modes array and make sure the receiving port is
|
||||
* added to the run loop to get data.
|
||||
*/
|
||||
loop = [NSRunLoop currentRunLoop];
|
||||
loop = [runLoopClass currentRunLoop];
|
||||
_runLoops = [[NSMutableArray alloc] initWithObjects: &loop count: 1];
|
||||
_requestModes = [[NSMutableArray alloc] initWithCapacity: 2];
|
||||
[self addRequestMode: NSDefaultRunLoopMode];
|
||||
|
@ -871,8 +881,7 @@ static int messages_received_count;
|
|||
|
||||
- (BOOL) multipleThreadsEnabled
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return NO;
|
||||
return _multipleThreads;
|
||||
}
|
||||
|
||||
- (NSPort*) receivePort
|
||||
|
@ -988,7 +997,7 @@ static int messages_received_count;
|
|||
|
||||
- (NSArray*) requestModes
|
||||
{
|
||||
return [[_requestModes copy] autorelease];
|
||||
return AUTORELEASE([_requestModes copy]);
|
||||
}
|
||||
|
||||
- (NSTimeInterval) requestTimeout
|
||||
|
@ -1023,7 +1032,10 @@ static int messages_received_count;
|
|||
|
||||
- (void) runInNewThread
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
[self removeRunLoop: [runLoopClass currentRunLoop]];
|
||||
[NSThread detachNewThreadSelector: @selector(_runInNewThread)
|
||||
toTarget: self
|
||||
withObject: nil];
|
||||
}
|
||||
|
||||
- (NSPort*) sendPort
|
||||
|
@ -1106,10 +1118,6 @@ static int messages_received_count;
|
|||
[d setObject: o forKey: NSConnectionLocalCount];
|
||||
o = [NSNumber numberWithUnsignedInt: NSCountMapTable(_remoteProxies)];
|
||||
[d setObject: o forKey: NSConnectionProxyCount];
|
||||
M_LOCK(received_request_rmc_queue_gate);
|
||||
o = [NSNumber numberWithUnsignedInt: [received_request_rmc_queue count]];
|
||||
M_UNLOCK(received_request_rmc_queue_gate);
|
||||
[d setObject: o forKey: @"Pending packets"];
|
||||
|
||||
M_UNLOCK(_refGate);
|
||||
|
||||
|
@ -1122,6 +1130,21 @@ static int messages_received_count;
|
|||
|
||||
@implementation NSConnection (GNUstepExtensions)
|
||||
|
||||
+ (NSConnection*) newRegisteringAtName: (NSString*)name
|
||||
withRootObject: (id)anObject
|
||||
{
|
||||
NSConnection *conn;
|
||||
|
||||
conn = [[self alloc] initWithReceivePort: [NSPort port]
|
||||
sendPort: nil];
|
||||
[conn setRootObject: anObject];
|
||||
if ([conn registerName: name] == NO)
|
||||
{
|
||||
DESTROY(conn);
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
- (void) gcFinalize
|
||||
{
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
|
@ -1190,8 +1213,8 @@ static int messages_received_count;
|
|||
_replyMap = 0;
|
||||
}
|
||||
|
||||
DESTROY(_cachedDecoder);
|
||||
DESTROY(_cachedEncoder);
|
||||
DESTROY(_cachedDecoders);
|
||||
DESTROY(_cachedEncoders);
|
||||
|
||||
DESTROY(_refGate);
|
||||
RELEASE(arp);
|
||||
|
@ -1368,19 +1391,19 @@ static int messages_received_count;
|
|||
|
||||
/* Class-wide stats and collections. */
|
||||
|
||||
+ (int) messagesReceived
|
||||
{
|
||||
return messages_received_count;
|
||||
}
|
||||
|
||||
+ (unsigned) connectionsCount
|
||||
{
|
||||
return NSCountHashTable(connection_table);
|
||||
unsigned result;
|
||||
|
||||
M_LOCK(connection_table_gate);
|
||||
result = NSCountHashTable(connection_table);
|
||||
M_UNLOCK(connection_table_gate);
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (unsigned) connectionsCountWithInPort: (NSPort*)aPort
|
||||
{
|
||||
unsigned count = 0;
|
||||
unsigned count = 0;
|
||||
NSHashEnumerator enumerator;
|
||||
NSConnection *o;
|
||||
|
||||
|
@ -1419,7 +1442,7 @@ static int messages_received_count;
|
|||
{
|
||||
NSLog(@"handling packet of type %d (%@)", type, stringFromMsgType(type));
|
||||
}
|
||||
conn = [NSConnection connectionWithReceivePort: rp sendPort: sp];
|
||||
conn = [connectionClass connectionWithReceivePort: rp sendPort: sp];
|
||||
if (conn == nil)
|
||||
{
|
||||
NSLog(@"received port message for unknown connection - %@", msg);
|
||||
|
@ -1542,6 +1565,14 @@ static int messages_received_count;
|
|||
}
|
||||
}
|
||||
|
||||
- (void) _runInNewThread
|
||||
{
|
||||
NSRunLoop *loop = [runLoopClass currentRunLoop];
|
||||
|
||||
[self addRunLoop: loop];
|
||||
[loop run];
|
||||
}
|
||||
|
||||
+ (void) setDebug: (int)val
|
||||
{
|
||||
debug_connection = val;
|
||||
|
@ -1767,8 +1798,8 @@ static int messages_received_count;
|
|||
}
|
||||
else
|
||||
{
|
||||
[NSDistantObject proxyWithLocal: counter->object
|
||||
connection: self];
|
||||
[distantObjectClass proxyWithLocal: counter->object
|
||||
connection: self];
|
||||
[op encodeObject: nil];
|
||||
if (debug_connection > 3)
|
||||
NSLog(@"retained object (0x%x) target (0x%x) on connection(0x%x)",
|
||||
|
@ -1843,17 +1874,6 @@ static int messages_received_count;
|
|||
}
|
||||
|
||||
|
||||
/* Running the connection, getting/sending requests/replies. */
|
||||
|
||||
- (void) runConnectionUntilDate: date
|
||||
{
|
||||
[NSRunLoop runUntilDate: date];
|
||||
}
|
||||
|
||||
- (void) runConnection
|
||||
{
|
||||
[self runConnectionUntilDate: [NSDate distantFuture]];
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the queue, then try to get it from the network by waiting
|
||||
|
@ -1870,11 +1890,12 @@ static int messages_received_count;
|
|||
{
|
||||
if (timeout_date == nil)
|
||||
{
|
||||
timeout_date = [NSDate dateWithTimeIntervalSinceNow: _replyTimeout];
|
||||
timeout_date
|
||||
= [dateClass dateWithTimeIntervalSinceNow: _replyTimeout];
|
||||
}
|
||||
M_UNLOCK(_queueGate);
|
||||
if ([NSRunLoop runOnceBeforeDate: timeout_date
|
||||
forMode: NSConnectionReplyMode] == NO)
|
||||
if ([runLoopClass runOnceBeforeDate: timeout_date
|
||||
forMode: NSConnectionReplyMode] == NO)
|
||||
{
|
||||
[NSException raise: NSPortTimeoutException
|
||||
format: @"timed out waiting for reply"];
|
||||
|
@ -1904,33 +1925,30 @@ static int messages_received_count;
|
|||
- (void) _doneInRmc: (NSPortCoder*)c
|
||||
{
|
||||
M_LOCK(_refGate);
|
||||
if (_cachedDecoder == nil)
|
||||
{
|
||||
_cachedDecoder = c;
|
||||
[c dispatch]; /* make coder release connection */
|
||||
}
|
||||
else
|
||||
{
|
||||
RELEASE(c);
|
||||
}
|
||||
[_cachedDecoders addObject: c];
|
||||
[c dispatch]; /* Tell NSPortCoder to release the connection. */
|
||||
RELEASE(c);
|
||||
M_UNLOCK(_refGate);
|
||||
}
|
||||
|
||||
- (NSPortCoder*) _makeInRmc: (NSMutableArray*)components
|
||||
{
|
||||
NSPortCoder *coder;
|
||||
NSPortCoder *coder;
|
||||
unsigned count;
|
||||
|
||||
NSParameterAssert(_isValid);
|
||||
|
||||
M_LOCK(_refGate);
|
||||
if (_cachedDecoder == nil)
|
||||
count = [_cachedDecoders count];
|
||||
if (count > 0)
|
||||
{
|
||||
coder = [NSPortCoder allocWithZone: NSDefaultMallocZone()];
|
||||
coder = [_cachedDecoders objectAtIndex: --count];
|
||||
RETAIN(coder);
|
||||
[_cachedDecoders removeObjectAtIndex: count];
|
||||
}
|
||||
else
|
||||
{
|
||||
coder = _cachedDecoder;
|
||||
_cachedDecoder = nil;
|
||||
coder = [portCoderClass allocWithZone: NSDefaultMallocZone()];
|
||||
}
|
||||
M_UNLOCK(_refGate);
|
||||
|
||||
|
@ -1942,19 +1960,22 @@ static int messages_received_count;
|
|||
|
||||
- (NSPortCoder*) _makeOutRmc: (int)sequence
|
||||
{
|
||||
NSPortCoder *coder;
|
||||
NSPortCoder *coder;
|
||||
unsigned count;
|
||||
|
||||
NSParameterAssert(_isValid);
|
||||
|
||||
M_LOCK(_refGate);
|
||||
if (_cachedEncoder == nil)
|
||||
count = [_cachedEncoders count];
|
||||
if (count > 0)
|
||||
{
|
||||
coder = [NSPortCoder allocWithZone: NSDefaultMallocZone()];
|
||||
coder = [_cachedEncoders objectAtIndex: --count];
|
||||
RETAIN(coder);
|
||||
[_cachedEncoders removeObjectAtIndex: count];
|
||||
}
|
||||
else
|
||||
{
|
||||
coder = _cachedEncoder;
|
||||
_cachedEncoder = nil;
|
||||
coder = [portCoderClass allocWithZone: NSDefaultMallocZone()];
|
||||
}
|
||||
M_UNLOCK(_refGate);
|
||||
|
||||
|
@ -1970,6 +1991,7 @@ static int messages_received_count;
|
|||
NSDate *limit;
|
||||
BOOL sent = NO;
|
||||
BOOL raiseException = NO;
|
||||
BOOL needsReply = NO;
|
||||
NSMutableArray *components = [c _components];
|
||||
|
||||
if (_authenticateOut == YES)
|
||||
|
@ -1985,7 +2007,30 @@ static int messages_received_count;
|
|||
}
|
||||
[components addObject: d];
|
||||
}
|
||||
limit = [NSDate dateWithTimeIntervalSinceNow: [self requestTimeout]];
|
||||
|
||||
switch (msgid)
|
||||
{
|
||||
case PROXY_RETAIN:
|
||||
needsReply = YES;
|
||||
case CONNECTION_SHUTDOWN:
|
||||
case METHOD_REPLY:
|
||||
case ROOTPROXY_REPLY:
|
||||
case METHODTYPE_REPLY:
|
||||
case PROXY_RELEASE:
|
||||
case RETAIN_REPLY:
|
||||
raiseException = NO;
|
||||
break;
|
||||
|
||||
case METHOD_REQUEST:
|
||||
case ROOTPROXY_REQUEST:
|
||||
case METHODTYPE_REQUEST:
|
||||
default:
|
||||
raiseException = YES;
|
||||
needsReply = YES;
|
||||
break;
|
||||
}
|
||||
|
||||
limit = [dateClass dateWithTimeIntervalSinceNow: _requestTimeout];
|
||||
sent = [_sendPort sendBeforeDate: limit
|
||||
msgid: msgid
|
||||
components: components
|
||||
|
@ -1993,41 +2038,35 @@ static int messages_received_count;
|
|||
reserved: [_sendPort reservedSpaceLength]];
|
||||
|
||||
M_LOCK(_refGate);
|
||||
if (_cachedEncoder == nil)
|
||||
/*
|
||||
* If we have sent out a request on a run loop that we don't already
|
||||
* know about, it must be on a new thread - so if we have multipleThreads
|
||||
* enabled, we must add the run loop of the new thread so that we can
|
||||
* get the reply in this thread.
|
||||
*/
|
||||
if (_multipleThreads == YES && needsReply == YES)
|
||||
{
|
||||
_cachedEncoder = c;
|
||||
[c dispatch]; /* make coder release connection */
|
||||
}
|
||||
else
|
||||
{
|
||||
RELEASE(c);
|
||||
NSRunLoop *loop = [runLoopClass currentRunLoop];
|
||||
|
||||
if ([_runLoops indexOfObjectIdenticalTo: loop] == NSNotFound)
|
||||
{
|
||||
[self addRunLoop: loop];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We replace the code we have just used in the cache, and tell it not to
|
||||
* retain this connection any more.
|
||||
*/
|
||||
[_cachedEncoders addObject: c];
|
||||
[c dispatch]; /* Tell NSPortCoder to release the connection. */
|
||||
RELEASE(c);
|
||||
M_UNLOCK(_refGate);
|
||||
|
||||
if (sent == NO)
|
||||
{
|
||||
NSString *text;
|
||||
NSString *text = stringFromMsgType(msgid);
|
||||
|
||||
switch (msgid)
|
||||
{
|
||||
case CONNECTION_SHUTDOWN:
|
||||
case METHOD_REPLY:
|
||||
case ROOTPROXY_REPLY:
|
||||
case METHODTYPE_REPLY:
|
||||
case PROXY_RELEASE:
|
||||
case PROXY_RETAIN:
|
||||
case RETAIN_REPLY:
|
||||
raiseException = YES;
|
||||
break;
|
||||
|
||||
case METHOD_REQUEST:
|
||||
case ROOTPROXY_REQUEST:
|
||||
case METHODTYPE_REQUEST:
|
||||
default:
|
||||
raiseException = YES;
|
||||
break;
|
||||
}
|
||||
text = stringFromMsgType(msgid);
|
||||
if (raiseException == YES)
|
||||
{
|
||||
[NSException raise: NSPortTimeoutException format: text];
|
||||
|
@ -2085,7 +2124,7 @@ static int messages_received_count;
|
|||
target = counter->target;
|
||||
NSMapInsert(all_connections_local_objects, (void*)object, counter);
|
||||
NSMapInsert(all_connections_local_targets, (void*)target, counter);
|
||||
[counter release];
|
||||
RELEASE(counter);
|
||||
}
|
||||
[anObj setProxyTarget: target];
|
||||
NSMapInsert(_localTargets, (void*)target, anObj);
|
||||
|
@ -2156,13 +2195,14 @@ static int messages_received_count;
|
|||
if (timer == nil)
|
||||
{
|
||||
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
|
||||
target: [NSConnection class]
|
||||
selector: @selector(_timeout: )
|
||||
target: connectionClass
|
||||
selector: @selector(_timeout:)
|
||||
userInfo: nil
|
||||
repeats: YES];
|
||||
}
|
||||
item = [CachedLocalObject itemWithObject: counter time: 30];
|
||||
item = [CachedLocalObject newWithObject: counter time: 30];
|
||||
NSMapInsert(all_connections_local_cached, (void*)target, item);
|
||||
RELEASE(item);
|
||||
if (debug_connection > 3)
|
||||
NSLog(@"placed local object (0x%x) target (0x%x) in cache",
|
||||
(gsaddr)anObj, target);
|
||||
|
@ -2289,7 +2329,7 @@ static int messages_received_count;
|
|||
unsigned target = (unsigned int)[aProxy targetForProxy];
|
||||
|
||||
NSParameterAssert (_isValid);
|
||||
NSParameterAssert(aProxy->isa == [NSDistantObject class]);
|
||||
NSParameterAssert(aProxy->isa == distantObjectClass);
|
||||
NSParameterAssert([aProxy connectionForProxy] == self);
|
||||
M_LOCK(_proxiesGate);
|
||||
if (NSMapGet(_remoteProxies, (void*)target))
|
||||
|
|
|
@ -278,7 +278,7 @@ typeCheck(char t1, char t2)
|
|||
|
||||
|
||||
|
||||
@interface NSPortCoder (Private)
|
||||
@interface NSPortCoder (Headers)
|
||||
- (void) _deserializeHeaderAt: (unsigned*)pos
|
||||
version: (unsigned*)v
|
||||
classes: (unsigned*)c
|
||||
|
@ -294,6 +294,22 @@ typeCheck(char t1, char t2)
|
|||
|
||||
@implementation NSPortCoder
|
||||
|
||||
static Class connectionClass;
|
||||
static Class mutableArrayClass;
|
||||
static Class mutableDataClass;
|
||||
static Class mutableDictionaryClass;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSPortCoder class])
|
||||
{
|
||||
connectionClass = [NSConnection class];
|
||||
mutableArrayClass = [NSMutableArray class];
|
||||
mutableDataClass = [NSMutableData class];
|
||||
mutableDictionaryClass = [NSMutableDictionary class];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSPortCoder*) portCoderWithReceivePort: (NSPort*)recv
|
||||
sendPort: (NSPort*)send
|
||||
components: (NSArray*)comp;
|
||||
|
@ -326,6 +342,12 @@ typeCheck(char t1, char t2)
|
|||
}
|
||||
if (_clsAry != 0)
|
||||
{
|
||||
unsigned count = GSIArrayCount(_clsAry);
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
RELEASE(GSIArrayItemAtIndex(_clsAry, count).obj);
|
||||
}
|
||||
GSIArrayClear(_clsAry);
|
||||
GSIArrayClear(_objAry);
|
||||
GSIArrayClear(_ptrAry);
|
||||
|
@ -422,7 +444,7 @@ typeCheck(char t1, char t2)
|
|||
}
|
||||
else if (pos == -2)
|
||||
{
|
||||
return [NSData data];
|
||||
return [mutableDataClass data];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -646,8 +668,6 @@ typeCheck(char t1, char t2)
|
|||
format: @"decoded nil class"];
|
||||
}
|
||||
classInfo = [GSClassInfo newWithClass: c andVersion: cver];
|
||||
[_cInfo addObject: classInfo];
|
||||
RELEASE(classInfo);
|
||||
GSIArrayAddItem(_clsAry, (GSIArrayItem)classInfo);
|
||||
*(Class*)address = classInfo->class;
|
||||
/*
|
||||
|
@ -925,7 +945,7 @@ typeCheck(char t1, char t2)
|
|||
#if GS_HAVE_I64
|
||||
bigval = val;
|
||||
#else
|
||||
val = GSSwapBigI64ToHost(val);
|
||||
bigval = GSSwapBigI64ToHost(val);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -1232,7 +1252,7 @@ typeCheck(char t1, char t2)
|
|||
(*_eValImp)(self, eValSel, @encode(Class), &cls);
|
||||
[obj encodeWithCoder: self];
|
||||
}
|
||||
else if (!_initialPass)
|
||||
else
|
||||
{
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_ID | _GSC_XREF, node->value.uint);
|
||||
}
|
||||
|
@ -1592,7 +1612,8 @@ typeCheck(char t1, char t2)
|
|||
|
||||
case _C_ULNG_LNG:
|
||||
(*_eTagImp)(_dst, eTagSel, _GSC_ULNG_LNG | _GSC_S_LNG_LNG);
|
||||
(*_eSerImp)(_dst, eSerSel, (void*)buf, @encode(unsigned long long), nil);
|
||||
(*_eSerImp)(_dst, eSerSel, (void*)buf, @encode(unsigned long long),
|
||||
nil);
|
||||
return;
|
||||
|
||||
case _C_FLT:
|
||||
|
@ -1621,8 +1642,8 @@ typeCheck(char t1, char t2)
|
|||
{
|
||||
BOOL firstTime;
|
||||
|
||||
_conn = RETAIN([NSConnection connectionWithReceivePort: recv
|
||||
sendPort: send]);
|
||||
_conn = RETAIN([connectionClass connectionWithReceivePort: recv
|
||||
sendPort: send]);
|
||||
if (_comp == nil)
|
||||
{
|
||||
firstTime = YES;
|
||||
|
@ -1657,8 +1678,8 @@ typeCheck(char t1, char t2)
|
|||
* the start for use by the port when the encoded data is sent.
|
||||
* Make the data item the first component of the array.
|
||||
*/
|
||||
_comp = [NSMutableArray new];
|
||||
_dst = [_fastCls._NSMutableDataMalloc allocWithZone: _zone];
|
||||
_comp = [mutableArrayClass new];
|
||||
_dst = [mutableDataClass allocWithZone: _zone];
|
||||
_dst = [_dst initWithLength: _cursor];
|
||||
[_comp addObject: _dst];
|
||||
RELEASE(_dst);
|
||||
|
@ -1744,12 +1765,7 @@ typeCheck(char t1, char t2)
|
|||
* _cInfo is a dictionary of objects for keeping track of the
|
||||
* version numbers that the classes were encoded with.
|
||||
*/
|
||||
if (firstTime == YES)
|
||||
{
|
||||
_cInfo
|
||||
= [[NSMutableArray allocWithZone: _zone] initWithCapacity: 16];
|
||||
}
|
||||
else
|
||||
if (firstTime == NO)
|
||||
{
|
||||
[_cInfo removeAllObjects];
|
||||
}
|
||||
|
@ -1778,12 +1794,18 @@ typeCheck(char t1, char t2)
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned count = GSIArrayCount(_clsAry);
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
RELEASE(GSIArrayItemAtIndex(_clsAry, count).obj);
|
||||
}
|
||||
GSIArrayRemoveAllItems(_clsAry);
|
||||
GSIArrayRemoveAllItems(_objAry);
|
||||
GSIArrayRemoveAllItems(_ptrAry);
|
||||
}
|
||||
GSIArrayAddItem(_clsAry, (GSIArrayItem)0);
|
||||
GSIArrayAddItem(_objAry, (GSIArrayItem)0);
|
||||
GSIArrayAddItem(_clsAry, (GSIArrayItem)nil);
|
||||
GSIArrayAddItem(_objAry, (GSIArrayItem)nil);
|
||||
GSIArrayAddItem(_ptrAry, (GSIArrayItem)0);
|
||||
}
|
||||
NS_HANDLER
|
||||
|
@ -1824,18 +1846,31 @@ typeCheck(char t1, char t2)
|
|||
|
||||
- (unsigned) versionForClassName: (NSString*)className
|
||||
{
|
||||
GSClassInfo *info;
|
||||
GSClassInfo *info = nil;
|
||||
unsigned version = NSNotFound;
|
||||
unsigned count = [_cInfo count];
|
||||
unsigned count = GSIArrayCount(_clsAry);
|
||||
|
||||
while (--count > 0)
|
||||
/*
|
||||
* Lazy ... we construct a dictionary of all the class information in
|
||||
* the request the first time that class version info is asked for.
|
||||
*/
|
||||
if (_cInfo == nil)
|
||||
{
|
||||
info = [_cInfo objectAtIndex: count];
|
||||
if ([[info className] isEqual: className] == YES)
|
||||
_cInfo = [[mutableDictionaryClass alloc] initWithCapacity: count];
|
||||
}
|
||||
if ([_cInfo count] == 0)
|
||||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
version = info->version;
|
||||
info = GSIArrayItemAtIndex(_clsAry, count).obj;
|
||||
[_cInfo setObject: info forKey: NSStringFromClass(info->class)];
|
||||
}
|
||||
}
|
||||
info = [_cInfo objectForKey: className];
|
||||
if (info != nil)
|
||||
{
|
||||
version = info->version;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@ -1850,6 +1885,10 @@ typeCheck(char t1, char t2)
|
|||
return _comp;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSPortCoder (Headers)
|
||||
|
||||
- (void) _deserializeHeaderAt: (unsigned*)pos
|
||||
version: (unsigned*)v
|
||||
classes: (unsigned*)c
|
||||
|
|
|
@ -51,8 +51,13 @@
|
|||
|
||||
extern int errno;
|
||||
|
||||
#if 0
|
||||
#define DO_LOCK(X) {NSDebugMLLog(@"GSTcpHandle",@"lock %@",X); [X lock];}
|
||||
#define DO_UNLOCK(X) {NSDebugMLLog(@"GSTcpHandle",@"unlock %@",X); [X unlock];}
|
||||
#else
|
||||
#define DO_LOCK(X) {[X lock];}
|
||||
#define DO_UNLOCK(X) {[X unlock];}
|
||||
#endif
|
||||
|
||||
#define GS_CONNECTION_MSG 0
|
||||
#define NETBLOCK 8192
|
||||
|
@ -305,6 +310,11 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
|
||||
@implementation GSTcpHandle
|
||||
|
||||
static Class mutableArrayClass;
|
||||
static Class mutableDataClass;
|
||||
static Class portMessageClass;
|
||||
static Class runLoopClass;
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
|
@ -344,6 +354,17 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
return AUTORELEASE(handle);
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [GSTcpHandle class])
|
||||
{
|
||||
mutableArrayClass = [NSMutableArray class];
|
||||
mutableDataClass = [NSMutableData class];
|
||||
portMessageClass = [NSPortMessage class];
|
||||
runLoopClass = [NSRunLoop class];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) connectToPort: (GSTcpPort*)aPort beforeDate: (NSDate*)when
|
||||
{
|
||||
NSArray *addrs;
|
||||
|
@ -428,7 +449,7 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
type: ET_WDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
while (state == GS_H_TRYCON && [when timeIntervalSinceNow] > 0)
|
||||
while (state == GS_H_TRYCON && [when timeIntervalSinceNow] > 0)
|
||||
{
|
||||
[l runMode: NSDefaultRunLoopMode beforeDate: when];
|
||||
}
|
||||
|
@ -487,15 +508,16 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
- (void) dispatch
|
||||
{
|
||||
NSPortMessage *pm;
|
||||
GSTcpPort *rp = [self recvPort];
|
||||
|
||||
pm = [NSPortMessage allocWithZone: NSDefaultMallocZone()];
|
||||
pm = [portMessageClass allocWithZone: NSDefaultMallocZone()];
|
||||
pm = [pm initWithSendPort: [self sendPort]
|
||||
receivePort: [self recvPort]
|
||||
receivePort: rp
|
||||
components: rItems];
|
||||
[pm setMsgid: rId];
|
||||
rId = 0;
|
||||
DESTROY(rItems);
|
||||
[[self recvPort] handlePortMessage: pm];
|
||||
[rp handlePortMessage: pm];
|
||||
RELEASE(pm);
|
||||
}
|
||||
|
||||
|
@ -536,15 +558,15 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
extra: (void*)extra
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpHandle", @"received %s event",
|
||||
type == ET_RPORT ? "read" : "write");
|
||||
NSDebugMLLog(@"GSTcpHandle", @"received %s event on 0x%x",
|
||||
type == ET_RPORT ? "read" : "write", self);
|
||||
/*
|
||||
* If we have been invalidated (desc < 0) then we should ignore this
|
||||
* event and remove ourself from the runloop.
|
||||
*/
|
||||
if (desc < 0)
|
||||
{
|
||||
NSRunLoop *l = [NSRunLoop currentRunLoop];
|
||||
NSRunLoop *l = [runLoopClass currentRunLoop];
|
||||
|
||||
[l removeEvent: data
|
||||
type: ET_WDESC
|
||||
|
@ -565,7 +587,7 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
*/
|
||||
if (rData == nil)
|
||||
{
|
||||
rData = [[NSMutableData alloc] initWithLength: NETBLOCK];
|
||||
rData = [[mutableDataClass alloc] initWithLength: NETBLOCK];
|
||||
rWant = sizeof(GSPortItemHeader);
|
||||
rLength = 0;
|
||||
want = NETBLOCK;
|
||||
|
@ -648,7 +670,7 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
memcpy(bytes, bytes + rWant, rLength);
|
||||
}
|
||||
rWant = sizeof(GSPortItemHeader);
|
||||
d = [NSData new];
|
||||
d = [mutableDataClass new];
|
||||
[rItems addObject: d];
|
||||
RELEASE(d);
|
||||
if (nItems == [rItems count])
|
||||
|
@ -686,7 +708,9 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
rId = GSSwapBigI32ToHost(h->mId);
|
||||
nItems = GSSwapBigI32ToHost(h->nItems);
|
||||
NSAssert(nItems >0, NSInternalInconsistencyException);
|
||||
rItems = [[NSMutableArray alloc] initWithCapacity: nItems];
|
||||
rItems
|
||||
= [mutableArrayClass allocWithZone: NSDefaultMallocZone()];
|
||||
rItems = [rItems initWithCapacity: nItems];
|
||||
if (rWant > sizeof(GSPortMsgHeader))
|
||||
{
|
||||
NSData *d;
|
||||
|
@ -696,7 +720,7 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
* the header - so add it to the rItems array.
|
||||
*/
|
||||
rWant -= sizeof(GSPortMsgHeader);
|
||||
d = [NSData alloc];
|
||||
d = [mutableDataClass alloc];
|
||||
d = [d initWithBytes: bytes + sizeof(GSPortMsgHeader)
|
||||
length: rWant];
|
||||
[rItems addObject: d];
|
||||
|
@ -733,7 +757,8 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
NSData *d;
|
||||
|
||||
rType = GSP_NONE;
|
||||
d = [[NSData alloc] initWithBytes: bytes length: rWant];
|
||||
d = [mutableDataClass allocWithZone: NSDefaultMallocZone()];
|
||||
d = [d initWithBytes: bytes length: rWant];
|
||||
[rItems addObject: d];
|
||||
RELEASE(d);
|
||||
rLength -= rWant;
|
||||
|
@ -838,7 +863,7 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"No messages to write.");
|
||||
NSLog(@"No messages to write on 0x%x.", self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -856,7 +881,8 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpHandle", @"wrote %d bytes", res);
|
||||
NSDebugMLLog(@"GSTcpHandle", @"wrote %d bytes on 0x%x",
|
||||
res, self);
|
||||
wLength += res;
|
||||
if (wLength == l)
|
||||
{
|
||||
|
@ -877,12 +903,21 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
}
|
||||
else
|
||||
{
|
||||
NSRunLoop *l = [runLoopClass currentRunLoop];
|
||||
|
||||
/*
|
||||
* message completed - remove from list.
|
||||
*/
|
||||
NSDebugMLLog(@"GSTcpHandle", @"completed 0x%x on 0x%x",
|
||||
components, self);
|
||||
wData = nil;
|
||||
wItem = 0;
|
||||
[wMsgs removeObjectAtIndex: 0];
|
||||
|
||||
[l removeEvent: data
|
||||
type: ET_WDESC
|
||||
forMode: mode
|
||||
all: NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -896,10 +931,11 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
BOOL sent = NO;
|
||||
|
||||
NSAssert([components count] > 0, NSInternalInconsistencyException);
|
||||
NSDebugMLLog(@"GSTcpHandle", @"Sending message before %@", when);
|
||||
NSDebugMLLog(@"GSTcpHandle", @"Sending message 0x%x on 0x%x(%d) before %@",
|
||||
components, self, desc, when);
|
||||
[wMsgs addObject: components];
|
||||
|
||||
l = [NSRunLoop currentRunLoop];
|
||||
l = [runLoopClass currentRunLoop];
|
||||
|
||||
RETAIN(self);
|
||||
|
||||
|
@ -912,16 +948,17 @@ newDataWithEncodedPort(GSTcpPort *port)
|
|||
{
|
||||
[l runMode: NSDefaultRunLoopMode beforeDate: when];
|
||||
}
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
/*
|
||||
* NB. We will remove ourself from the run loop when the message send
|
||||
* is completed, so we don't need to do it here.
|
||||
*/
|
||||
if ([wMsgs indexOfObjectIdenticalTo: components] == NSNotFound)
|
||||
{
|
||||
sent = YES;
|
||||
}
|
||||
RELEASE(self);
|
||||
NSDebugMLLog(@"GSTcpHandle", @"Message send %d", sent);
|
||||
NSDebugMLLog(@"GSTcpHandle", @"Message send 0x%x on 0x%x status %d",
|
||||
components, self, sent);
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
@ -1575,7 +1612,7 @@ static NSMapTable *tcpPortMap = 0;
|
|||
*/
|
||||
if (length == 0 && rl != 0)
|
||||
{
|
||||
header = [[NSMutableData alloc] initWithCapacity: NETBLOCK];
|
||||
header = [[mutableDataClass alloc] initWithCapacity: NETBLOCK];
|
||||
|
||||
[header setLength: rl];
|
||||
[components insertObject: header atIndex: 0];
|
||||
|
|
|
@ -359,7 +359,8 @@ static SEL eValSel = @selector(encodeValueOfObjCType:at:);
|
|||
/*
|
||||
* Second pass, write a cross-reference number.
|
||||
*/
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_PTR|_GSC_XREF, node->value.uint);
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_PTR|_GSC_XREF,
|
||||
node->value.uint);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -425,8 +426,8 @@ static SEL eValSel = @selector(encodeValueOfObjCType:at:);
|
|||
* of its subclasses are decoded and call
|
||||
* [super initWithCoder:ccc]
|
||||
*/
|
||||
if (s == c || s == 0 ||
|
||||
GSIMapNodeForKey(_clsMap, (GSIMapKey)(void*)s) != 0)
|
||||
if (s == c || s == 0
|
||||
|| GSIMapNodeForKey(_clsMap, (GSIMapKey)(void*)s) != 0)
|
||||
{
|
||||
done = YES;
|
||||
}
|
||||
|
@ -458,7 +459,7 @@ static SEL eValSel = @selector(encodeValueOfObjCType:at:);
|
|||
if (node == 0)
|
||||
{
|
||||
node = GSIMapAddPair(_ptrMap,
|
||||
(GSIMapKey)(void*)s, (GSIMapVal)++_xRefP);
|
||||
(GSIMapKey)(void*)s, (GSIMapVal)++_xRefP);
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_SEL, node->value.uint);
|
||||
/*
|
||||
* Encode selector.
|
||||
|
@ -467,7 +468,8 @@ static SEL eValSel = @selector(encodeValueOfObjCType:at:);
|
|||
}
|
||||
else
|
||||
{
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_SEL|_GSC_XREF, node->value.uint);
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_SEL|_GSC_XREF,
|
||||
node->value.uint);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -784,7 +786,7 @@ static SEL eValSel = @selector(encodeValueOfObjCType:at:);
|
|||
(*_eValImp)(self, eValSel, @encode(Class), &cls);
|
||||
[obj encodeWithCoder: self];
|
||||
}
|
||||
else if(!_initialPass)
|
||||
else
|
||||
{
|
||||
(*_xRefImp)(_dst, xRefSel, _GSC_ID | _GSC_XREF, node->value.uint);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,20 @@ static int debug_proxy = 0;
|
|||
static Class placeHolder = 0;
|
||||
static Class distantObjectClass = 0;
|
||||
|
||||
typedef struct {
|
||||
@defs(NSDistantObject)
|
||||
} NSDO;
|
||||
|
||||
/* This is the proxy tag; it indicates where the local object is,
|
||||
and determines whether the reply port to the Connection-where-the-
|
||||
proxy-is-local needs to encoded/decoded or not. */
|
||||
enum
|
||||
{
|
||||
PROXY_LOCAL_FOR_RECEIVER = 0,
|
||||
PROXY_LOCAL_FOR_SENDER,
|
||||
PROXY_REMOTE_FOR_BOTH
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -77,11 +91,172 @@ static Class distantObjectClass = 0;
|
|||
|
||||
+ (id) initWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
NSDistantObject *proxy;
|
||||
gsu8 proxy_tag;
|
||||
unsigned target;
|
||||
id decoder_connection;
|
||||
|
||||
proxy = (NSDistantObject*)NSAllocateObject(distantObjectClass,
|
||||
0, NSDefaultMallocZone());
|
||||
return [proxy initWithCoder: aCoder];
|
||||
/*
|
||||
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"NSDistantObject objects only decode with "
|
||||
@"NSPortCoder class"];
|
||||
}
|
||||
*/
|
||||
|
||||
decoder_connection = [(NSPortCoder*)aCoder connection];
|
||||
NSAssert(decoder_connection, NSInternalInconsistencyException);
|
||||
|
||||
/* First get the tag, so we know what values need to be decoded. */
|
||||
[aCoder decodeValueOfObjCType: @encode(typeof(proxy_tag))
|
||||
at: &proxy_tag];
|
||||
|
||||
switch (proxy_tag)
|
||||
{
|
||||
case PROXY_LOCAL_FOR_RECEIVER:
|
||||
/*
|
||||
* This was a proxy on the other side of the connection, but
|
||||
* here it's local.
|
||||
* Lookup the target handle to ensure that it exists here.
|
||||
* Return a retained copy of the local target object.
|
||||
*/
|
||||
[aCoder decodeValueOfObjCType: @encode(typeof(target))
|
||||
at: &target];
|
||||
|
||||
if (debug_proxy)
|
||||
NSLog(@"Receiving a proxy for local object 0x%x "
|
||||
@"connection 0x%x\n", target, (gsaddr)decoder_connection);
|
||||
|
||||
if (![[decoder_connection class] includesLocalTarget: target])
|
||||
{
|
||||
[NSException raise: @"ProxyDecodedBadTarget"
|
||||
format: @"No local object with given target (0x%x)",
|
||||
target];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDistantObject *o;
|
||||
|
||||
o = [decoder_connection includesLocalTarget: target];
|
||||
if (debug_proxy)
|
||||
{
|
||||
NSLog(@"Local object is 0x%x (0x%x)\n",
|
||||
(gsaddr)o, (gsaddr)o ? ((NSDO*)o)->_object : 0);
|
||||
}
|
||||
return o ? RETAIN(((NSDO*)o)->_object) : nil;
|
||||
}
|
||||
|
||||
case PROXY_LOCAL_FOR_SENDER:
|
||||
/*
|
||||
* This was a local object on the other side of the connection,
|
||||
* but here it's a proxy object. Get the target address, and
|
||||
* send [NSDistantObject +proxyWithTarget:connection:]; this will
|
||||
* return the proxy object we already created for this target, or
|
||||
* create a new proxy object if necessary.
|
||||
*/
|
||||
[aCoder decodeValueOfObjCType: @encode(typeof(target))
|
||||
at: &target];
|
||||
if (debug_proxy)
|
||||
NSLog(@"Receiving a proxy, was local 0x%x connection 0x%x\n",
|
||||
target, (gsaddr)decoder_connection);
|
||||
return [self initWithTarget: target
|
||||
connection: decoder_connection];
|
||||
|
||||
case PROXY_REMOTE_FOR_BOTH:
|
||||
/*
|
||||
* This was a proxy on the other side of the connection, and it
|
||||
* will be a proxy on this side too; that is, the local version
|
||||
* of this object is not on this host, not on the host the
|
||||
* NSPortCoder is connected to, but on a *third* host.
|
||||
* This is why I call this a "triangle connection". In addition
|
||||
* to decoding the target, we decode the OutPort object that we
|
||||
* will use to talk directly to this third host. We send
|
||||
* [NSConnection +newForInPort:outPort:ancestorConnection:]; this
|
||||
* will either return the connection already created for this
|
||||
* inPort/outPort pair, or create a new connection if necessary.
|
||||
*/
|
||||
{
|
||||
NSConnection *proxy_connection;
|
||||
NSPort *proxy_connection_out_port = nil;
|
||||
unsigned intermediary;
|
||||
|
||||
/*
|
||||
* There is an object on the intermediary host that is keeping
|
||||
* that hosts proxy for the original object retained, thus
|
||||
* ensuring that the original is not released. We create a
|
||||
* proxy for that intermediate proxy. When we release this
|
||||
* proxy, the intermediary will be free to release it's proxy
|
||||
* and the original can then be released. Of course, by that
|
||||
* time we will have obtained our own proxy for the original
|
||||
* object ...
|
||||
*/
|
||||
[aCoder decodeValueOfObjCType: @encode(typeof(intermediary))
|
||||
at: &intermediary];
|
||||
AUTORELEASE([self initWithTarget: intermediary
|
||||
connection: decoder_connection]);
|
||||
|
||||
/*
|
||||
* Now we get the target number and port for the orignal object
|
||||
* and (if necessary) get the originating process to retain the
|
||||
* object for us.
|
||||
*/
|
||||
[aCoder decodeValueOfObjCType: @encode(typeof(target))
|
||||
at: &target];
|
||||
|
||||
[aCoder decodeValueOfObjCType: @encode(id)
|
||||
at: &proxy_connection_out_port];
|
||||
|
||||
NSAssert(proxy_connection_out_port, NSInternalInconsistencyException);
|
||||
/*
|
||||
# If there already exists a connection for talking to the
|
||||
* out port, we use that one rather than creating a new one from
|
||||
* our listening port.
|
||||
*
|
||||
* First we try for a connection from our receive port,
|
||||
* Then we try any connection to the send port
|
||||
* Finally we resort to creating a new connection - we don't
|
||||
* release the newly created connection - it will get released
|
||||
* automatically when no proxies are left on it.
|
||||
*/
|
||||
proxy_connection = [[decoder_connection class]
|
||||
connectionWithReceivePort: [decoder_connection receivePort]
|
||||
sendPort: proxy_connection_out_port];
|
||||
|
||||
if (debug_proxy)
|
||||
NSLog(@"Receiving a triangle-connection proxy 0x%x "
|
||||
@"connection 0x%x\n", target, (gsaddr)proxy_connection);
|
||||
|
||||
NSAssert(proxy_connection != decoder_connection,
|
||||
NSInternalInconsistencyException);
|
||||
NSAssert([proxy_connection isValid],
|
||||
NSInternalInconsistencyException);
|
||||
|
||||
/*
|
||||
* If we don't already have a proxy for the object on the
|
||||
* remote system, we must tell the other end to retain its
|
||||
* local object for our use.
|
||||
*/
|
||||
if ([proxy_connection includesProxyForTarget: target] == NO)
|
||||
[proxy_connection retainTarget: target];
|
||||
|
||||
/*
|
||||
* Finally - we get a proxy via a direct connection to the
|
||||
* originating server. We have also created a proxy to an
|
||||
* intermediate object - but this proxy has not been retained
|
||||
* and will therefore go away when the current autorelease
|
||||
* pool is destroyed.
|
||||
*/
|
||||
return [self initWithTarget: target
|
||||
connection: proxy_connection];
|
||||
}
|
||||
|
||||
default:
|
||||
/* xxx This should be something different than NSGenericException. */
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Bad proxy tag"];
|
||||
}
|
||||
/* Not reached. */
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id) initWithLocal: (id)anObject connection: (NSConnection*)aConnection
|
||||
|
@ -138,16 +313,6 @@ static Class distantObjectClass = 0;
|
|||
|
||||
@implementation NSDistantObject
|
||||
|
||||
/* This is the proxy tag; it indicates where the local object is,
|
||||
and determines whether the reply port to the Connection-where-the-
|
||||
proxy-is-local needs to encoded/decoded or not. */
|
||||
enum
|
||||
{
|
||||
PROXY_LOCAL_FOR_RECEIVER = 0,
|
||||
PROXY_LOCAL_FOR_SENDER,
|
||||
PROXY_REMOTE_FOR_BOTH
|
||||
};
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSDistantObject class])
|
||||
|
|
|
@ -881,7 +881,7 @@ mapClassName(NSUnarchiverObjectInfo *info)
|
|||
#if GS_HAVE_I64
|
||||
bigval = val;
|
||||
#else
|
||||
val = GSSwapBigI64ToHost(val);
|
||||
bigval = GSSwapBigI64ToHost(val);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue