Preliminary 64-bit clean work.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3588 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-01-24 09:29:13 +00:00
parent ff8b01532f
commit 299fac65f5
6 changed files with 482 additions and 394 deletions

View file

@ -1,3 +1,12 @@
Sun Jan 24 8:50:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* src/NSConnection.m: Preliminary work for handling DO between
machines wiuth different pointer sizes.
* src/NSDistantObject.m: ditto
* src/include/NSConnection.h: ditto
* src/include/NSDistantObject.h: ditto
* src/include/DistributedObjects.h: ditto
Tue Jan 19 12:20:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk> Tue Jan 19 12:20:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* src/NSUserDefaults.m: Fixed to update periodically from disk and * src/NSUserDefaults.m: Fixed to update periodically from disk and

View file

@ -74,9 +74,12 @@ enum {
+ (NSConnection*) connectionByInPort: (NSPort*)ip + (NSConnection*) connectionByInPort: (NSPort*)ip
outPort: (NSPort*)op; outPort: (NSPort*)op;
+ (NSConnection*) connectionByOutPort: (NSPort*)op; + (NSConnection*) connectionByOutPort: (NSPort*)op;
- (NSDistantObject*) localForTarget: (void*)target; + (NSDistantObject*) includesLocalTarget: (gsu32)target;
- (NSDistantObject*) proxyForTarget: (void*)target; - (NSDistantObject*) includesLocalTarget: (gsu32)target;
- (void) retainTarget: (unsigned)target; - (NSDistantObject*) localForObject: (id)object;
- (NSDistantObject*) localForTarget: (gsu32)target;
- (NSDistantObject*) proxyForTarget: (gsu32)target;
- (void) retainTarget: (gsu32)target;
- (void) setNotOwned; - (void) setNotOwned;
@end @end

View file

@ -70,6 +70,7 @@ extern NSString *NSConnectionProxyCount; /* Objects received */
unsigned req_in_count; unsigned req_in_count;
unsigned rep_out_count; unsigned rep_out_count;
unsigned rep_in_count; unsigned rep_in_count;
NSMapTable *local_objects;
NSMapTable *local_targets; NSMapTable *local_targets;
NSMapTable *remote_proxies; NSMapTable *remote_proxies;
NSTimeInterval reply_timeout; NSTimeInterval reply_timeout;
@ -220,7 +221,7 @@ extern NSString *NSConnectionProxyCount; /* Objects received */
/* Only subclassers and power-users need worry about these */ /* Only subclassers and power-users need worry about these */
- (void) addProxy: (NSDistantObject*)aProxy; - (void) addProxy: (NSDistantObject*)aProxy;
- (id) includesProxyForTarget: (void*)target; - (id) includesProxyForTarget: (gsu32)target;
- (void) removeProxy: (NSDistantObject*)aProxy; - (void) removeProxy: (NSDistantObject*)aProxy;
// It seems to be a non pure-OPENSTEP definition... // It seems to be a non pure-OPENSTEP definition...

View file

@ -34,33 +34,39 @@
@private @private
NSConnection *_connection; NSConnection *_connection;
id _object; id _object;
BOOL _isLocal; gsu32 _handle;
BOOL _isVended; BOOL _isVended;
Protocol *_protocol; Protocol *_protocol;
} }
+ (NSDistantObject*) proxyWithLocal: anObject + (NSDistantObject*) proxyWithLocal: (id)anObject
connection: (NSConnection*)aConnection; connection: (NSConnection*)aConnection;
+ (NSDistantObject*) proxyWithTarget: anObject /*
* NB. Departure from the OpenStep/MacOS spec - the type of a target
* is a 32-bit integer, not an id, since we can't safely pass id's
* between address spaces on machines with different pointer sizes.
*/
+ (NSDistantObject*) proxyWithTarget: (gsu32)anObject
connection: (NSConnection*)aConnection; connection: (NSConnection*)aConnection;
- (NSConnection*) connectionForProxy; - (NSConnection*) connectionForProxy;
- initWithLocal:anObject connection: (NSConnection*)aConnection; - (id) initWithLocal: (id)anObject connection: (NSConnection*)aConnection;
- initWithTarget:anObject connection: (NSConnection*)aConnection; - (id) initWithTarget: (gsu32)anObject connection: (NSConnection*)aConnection;
- (void) setProtocolForProxy: (Protocol*)aProtocol; - (void) setProtocolForProxy: (Protocol*)aProtocol;
@end @end
@interface NSDistantObject(GNUstepExtensions) @interface NSDistantObject(GNUstepExtensions)
+ newForRemoteTarget: (unsigned)target connection: (NSConnection*)conn; + newForRemoteTarget: (gsu32)target connection: (NSConnection*)conn;
- awakeAfterUsingCoder: aDecoder; - awakeAfterUsingCoder: aDecoder;
- classForPortCoder; - classForPortCoder;
+ newWithCoder: aRmc; + newWithCoder: aRmc;
- (const char *) selectorTypeForProxy: (SEL)selector; - (const char *) selectorTypeForProxy: (SEL)selector;
- forward: (SEL)aSel :(arglist_t)frame; - forward: (SEL)aSel :(arglist_t)frame;
- targetForProxy; - (id) localForProxy;
- (gsu32) targetForProxy;
@end @end
#endif /* __NSDistantObject_h_GNUSTEP_BASE_INCLUDE */ #endif /* __NSDistantObject_h_GNUSTEP_BASE_INCLUDE */

View file

@ -254,6 +254,7 @@ static NSLock *root_object_dictionary_gate;
static NSMapTable *receive_port_2_ancestor; static NSMapTable *receive_port_2_ancestor;
static NSMapTable *all_connections_local_objects = NULL;
static NSMapTable *all_connections_local_targets = NULL; static NSMapTable *all_connections_local_targets = NULL;
static NSMapTable *all_connections_local_cached = NULL; static NSMapTable *all_connections_local_cached = NULL;
@ -327,9 +328,12 @@ static int messages_received_count;
connection_array = [[NSMutableArray alloc] initWithCapacity:8]; connection_array = [[NSMutableArray alloc] initWithCapacity:8];
connection_array_gate = [NSLock new]; connection_array_gate = [NSLock new];
/* xxx When NSHashTable's are working, change this. */ /* xxx When NSHashTable's are working, change this. */
all_connections_local_targets = all_connections_local_objects =
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0); NSObjectMapValueCallBacks, 0);
all_connections_local_targets =
NSCreateMapTable (NSIntMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
all_connections_local_cached = all_connections_local_cached =
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0); NSObjectMapValueCallBacks, 0);
@ -431,6 +435,7 @@ static int messages_received_count;
[proxiesHashGate lock]; [proxiesHashGate lock];
NSFreeMapTable (remote_proxies); NSFreeMapTable (remote_proxies);
NSFreeMapTable (local_objects);
NSFreeMapTable (local_targets); NSFreeMapTable (local_targets);
NSFreeMapTable (incoming_xref_2_const_ptr); NSFreeMapTable (incoming_xref_2_const_ptr);
NSFreeMapTable (outgoing_const_ptr_2_xref); NSFreeMapTable (outgoing_const_ptr_2_xref);
@ -522,7 +527,7 @@ static int messages_received_count;
targets = [NSAllMapTableValues(local_targets) retain]; targets = [NSAllMapTableValues(local_targets) retain];
for (i = 0; i < [targets count]; i++) for (i = 0; i < [targets count]; i++)
{ {
id t = [[targets objectAtIndex:i] targetForProxy]; id t = [[targets objectAtIndex:i] localForProxy];
[self removeLocalObject:t]; [self removeLocalObject:t];
} }
@ -925,10 +930,15 @@ static int messages_received_count;
/* 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. */
newConn->local_targets = newConn->local_objects =
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
NSObjectMapValueCallBacks, 0); 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. */ /* This maps [proxy targetForProxy] to proxy. The proxy's are retained. */
newConn->remote_proxies = newConn->remote_proxies =
NSCreateMapTable (NSIntMapKeyCallBacks, NSCreateMapTable (NSIntMapKeyCallBacks,
@ -1437,7 +1447,7 @@ static int messages_received_count;
withName: NULL]; withName: NULL];
for (pos = 0; pos < count; pos++) { for (pos = 0; pos < count; pos++) {
unsigned int target; gsu32 target;
char vended; char vended;
NSDistantObject *prox; NSDistantObject *prox;
@ -1463,7 +1473,7 @@ static int messages_received_count;
- (void) _service_retain: rmc forConnection: receiving_connection - (void) _service_retain: rmc forConnection: receiving_connection
{ {
unsigned int target; gsu32 target;
NSParameterAssert (is_valid); NSParameterAssert (is_valid);
@ -1508,7 +1518,7 @@ static int messages_received_count;
[rmc dismiss]; [rmc dismiss];
} }
- (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target - (const char *) typeForSelector: (SEL)sel remoteTarget: (gsu32)target
{ {
id op, ip; id op, ip;
char *type = 0; char *type = 0;
@ -1524,7 +1534,7 @@ static int messages_received_count;
[op encodeValueOfObjCType:":" [op encodeValueOfObjCType:":"
at:&sel at:&sel
withName:NULL]; withName:NULL];
[op encodeValueOfCType:@encode(unsigned) [op encodeValueOfCType:@encode(gsu32)
at:&target at:&target
withName:NULL]; withName:NULL];
[op dismiss]; [op dismiss];
@ -1539,7 +1549,9 @@ static int messages_received_count;
- (void) _service_typeForSelector: rmc - (void) _service_typeForSelector: rmc
{ {
NSPortCoder* op; NSPortCoder* op;
unsigned target; gsu32 target;
NSDistantObject *p;
id o;
SEL sel; SEL sel;
const char *type; const char *type;
struct objc_method* m; struct objc_method* m;
@ -1555,12 +1567,15 @@ static int messages_received_count;
[rmc decodeValueOfObjCType:":" [rmc decodeValueOfObjCType:":"
at:&sel at:&sel
withName:NULL]; withName:NULL];
[rmc decodeValueOfCType:@encode(unsigned) [rmc decodeValueOfCType:@encode(gsu32)
at:&target at:&target
withName:NULL]; withName:NULL];
p = [self includesLocalTarget: target];
o = [p localForProxy];
/* xxx We should make sure that TARGET is a valid object. */ /* xxx We should make sure that TARGET is a valid object. */
/* Not actually a Proxy, but we avoid the warnings "id" would have made. */ /* Not actually a Proxy, but we avoid the warnings "id" would have made. */
m = class_get_instance_method(((NSDistantObject*)target)->isa, sel); m = class_get_instance_method((o)->isa, sel);
/* Perhaps I need to be more careful in the line above to get the /* Perhaps I need to be more careful in the line above to get the
version of the method types that has the type qualifiers in it. version of the method types that has the type qualifiers in it.
Search the protocols list. */ Search the protocols list. */
@ -1764,47 +1779,52 @@ static int messages_received_count;
/* Managing objects and proxies. */ /* Managing objects and proxies. */
- (void) addLocalObject: anObj - (void) addLocalObject: anObj
{ {
id local = [anObj targetForProxy]; id object = [anObj localForProxy];
gsu32 target = [anObj targetForProxy];
id counter; id counter;
NSParameterAssert (is_valid); NSParameterAssert (is_valid);
[proxiesHashGate lock]; [proxiesHashGate lock];
/* xxx Do we need to check to make sure it's not already there? */ /* xxx Do we need to check to make sure it's not already there? */
/* This retains anObj. */ /* This retains anObj. */
NSMapInsert(local_targets, (void*)local, anObj); NSMapInsert(local_objects, (void*)object, anObj);
NSMapInsert(local_targets, (void*)target, anObj);
/* /*
* Keep track of local objects accross all connections. * Keep track of local objects accross all connections.
*/ */
counter = NSMapGet(all_connections_local_targets, (void*)local); counter = NSMapGet(all_connections_local_objects, (void*)object);
if (counter) { if (counter)
{
[counter increment]; [counter increment];
} }
else { else
{
counter = [ConnectionLocalCounter new]; counter = [ConnectionLocalCounter new];
NSMapInsert(all_connections_local_targets, (void*)local, counter); NSMapInsert(all_connections_local_objects, (void*)object, counter);
NSMapInsert(all_connections_local_targets, (void*)target, counter);
[counter release]; [counter release];
} }
if (debug_connection > 2) if (debug_connection > 2)
NSLog(@"add local object (0x%x) to connection (0x%x) (ref %d)\n", NSLog(@"add local object (0x%x) to connection (0x%x) (ref %d)\n",
(unsigned)local, (unsigned) self, [counter value]); (unsigned)object, (unsigned) self, [counter value]);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
} }
- (NSDistantObject*) localForTarget: (void*)target - (NSDistantObject*) localForObject: (id)object
{ {
NSDistantObject *p; NSDistantObject *p;
/* Don't assert (is_valid); */ /* Don't assert (is_valid); */
[proxiesHashGate lock]; [proxiesHashGate lock];
p = NSMapGet (local_targets, target); p = NSMapGet (local_objects, (void*)object);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
NSParameterAssert(!p || [p connectionForProxy] == self); NSParameterAssert(!p || [p connectionForProxy] == self);
return p; return p;
} }
/* This should get called whenever an object free's itself */ /* This should get called whenever an object free's itself */
+ (void) removeLocalObject: anObj + (void) removeLocalObject: (id)anObj
{ {
id c; id c;
int i, count = [connection_array count]; int i, count = [connection_array count];
@ -1820,6 +1840,8 @@ static int messages_received_count;
- (void) removeLocalObject: anObj - (void) removeLocalObject: anObj
{ {
NSDistantObject *prox = NSMapGet(local_objects, (void*)anObj);
gsu32 target = [prox targetForProxy];
id counter; id counter;
unsigned val = 0; unsigned val = 0;
@ -1829,21 +1851,24 @@ static int messages_received_count;
* If all references to a local proxy have gone - remove the * If all references to a local proxy have gone - remove the
* global reference as well. * global reference as well.
*/ */
counter = NSMapGet(all_connections_local_targets, (void*)anObj); counter = NSMapGet(all_connections_local_objects, (void*)anObj);
if (counter) { if (counter)
{
[counter decrement]; [counter decrement];
if ((val = [counter value]) == 0) { if ((val = [counter value]) == 0)
NSDistantObject *prox = NSMapGet(local_targets, (void*)anObj); {
NSMapRemove(all_connections_local_objects, (void*)anObj);
NSMapRemove(all_connections_local_targets, (void*)anObj); NSMapRemove(all_connections_local_targets, (void*)target);
/* /*
* If this proxy has been vended onwards by another process, we * If this proxy has been vended onwards by another process, we
* need to keep a reference to the local object around for a * need to keep a reference to the local object around for a
* while in case that other process needs it. * while in case that other process needs it.
*/ */
if ([prox isVended]) { if ([prox isVended])
{
id item; id item;
if (timer == nil) { if (timer == nil)
{
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
target: [NSConnection class] target: [NSConnection class]
selector: @selector(_timeout:) selector: @selector(_timeout:)
@ -1856,7 +1881,8 @@ static int messages_received_count;
} }
} }
NSMapRemove (local_targets, (void*)anObj); NSMapRemove(local_objects, (void*)anObj);
NSMapRemove(local_targets, (void*)target);
if (debug_connection > 2) if (debug_connection > 2)
NSLog(@"remove local object (0x%x) to connection (0x%x) (ref %d)\n", NSLog(@"remove local object (0x%x) to connection (0x%x) (ref %d)\n",
@ -1888,7 +1914,7 @@ static int messages_received_count;
withName: NULL]; withName: NULL];
for (i = 0; i < number; i++) { for (i = 0; i < number; i++) {
unsigned target = (unsigned)[list[i] targetForProxy]; gsu32 target = [list[i] targetForProxy];
char vended = [list[i] isVended]; char vended = [list[i] isVended];
[op encodeValueOfCType: @encode(typeof(target)) [op encodeValueOfCType: @encode(typeof(target))
@ -1910,7 +1936,7 @@ static int messages_received_count;
NS_ENDHANDLER NS_ENDHANDLER
} }
- (void) retainTarget: (unsigned int)target - (void) retainTarget: (gsu32)target
{ {
NS_DURING NS_DURING
{ {
@ -1918,7 +1944,8 @@ static int messages_received_count;
* Tell the remote app that it must retain the local object * Tell the remote app that it must retain the local object
* for the target on this connection. * for the target on this connection.
*/ */
if (receive_port && is_valid) { if (receive_port && is_valid)
{
id op; id op;
unsigned int i; unsigned int i;
int seq_num = [self _newMsgNumber]; int seq_num = [self _newMsgNumber];
@ -1966,7 +1993,7 @@ static int messages_received_count;
/* Don't assert (is_valid); */ /* Don't assert (is_valid); */
[proxiesHashGate lock]; [proxiesHashGate lock];
c = NSAllMapTableValues (local_targets); c = NSAllMapTableValues (local_objects);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
return c; return c;
} }
@ -1982,13 +2009,13 @@ static int messages_received_count;
return c; return c;
} }
- (NSDistantObject*) proxyForTarget: (void*)target - (NSDistantObject*) proxyForTarget: (gsu32)target
{ {
NSDistantObject *p; NSDistantObject *p;
/* Don't assert (is_valid); */ /* Don't assert (is_valid); */
[proxiesHashGate lock]; [proxiesHashGate lock];
p = NSMapGet (remote_proxies, target); p = NSMapGet (remote_proxies, (void*)target);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
NSParameterAssert(!p || [p connectionForProxy] == self); NSParameterAssert(!p || [p connectionForProxy] == self);
return p; return p;
@ -2009,7 +2036,7 @@ static int messages_received_count;
[proxiesHashGate unlock]; [proxiesHashGate unlock];
} }
- (id) includesProxyForTarget: (void*)target - (id) includesProxyForTarget: (gsu32)target
{ {
NSDistantObject *ret; NSDistantObject *ret;
@ -2020,13 +2047,24 @@ static int messages_received_count;
return ret; return ret;
} }
- (id) includesLocalObject: anObj - (id) includesLocalObject: (id)anObj
{ {
NSDistantObject* ret; NSDistantObject* ret;
/* Don't assert (is_valid); */ /* Don't assert (is_valid); */
[proxiesHashGate lock]; [proxiesHashGate lock];
ret = NSMapGet(local_targets, (void*)anObj); ret = NSMapGet(local_objects, (void*)anObj);
[proxiesHashGate unlock];
return ret;
}
- (id) includesLocalTarget: (gsu32)target
{
NSDistantObject* ret;
/* Don't assert (is_valid); */
[proxiesHashGate lock];
ret = NSMapGet(local_targets, (void*)target);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
return ret; return ret;
} }
@ -2035,9 +2073,9 @@ static int messages_received_count;
Proxy needs to use this when decoding a local object in order to Proxy needs to use this when decoding a local object in order to
make sure the target address is a valid object. It is not enough make sure the target address is a valid object. It is not enough
for the Proxy to check the Proxy's connection only (using for the Proxy to check the Proxy's connection only (using
-includesLocalObject), because the proxy may have come from a -includesLocalTarget), because the proxy may have come from a
triangle connection. */ triangle connection. */
+ (id) includesLocalObject: anObj + (id) includesLocalTarget: (gsu32)anObj
{ {
id ret; id ret;

View file

@ -24,6 +24,7 @@
#include <config.h> #include <config.h>
#include <Foundation/DistributedObjects.h> #include <Foundation/DistributedObjects.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSMethodSignature.h> #include <Foundation/NSMethodSignature.h>
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
@ -52,32 +53,39 @@ enum
PROXY_REMOTE_FOR_BOTH PROXY_REMOTE_FOR_BOTH
}; };
static gsu32 handle_counter = 0;
static NSRecursiveLock *handle_lock = nil;
+ (void) initialize + (void) initialize
{ {
return; if (self == [NSDistantObject class])
{
handle_lock = [NSRecursiveLock new];
}
} }
+ (NSDistantObject*) proxyWithLocal: anObject + (NSDistantObject*) proxyWithLocal: (id)anObject
connection: (NSConnection*)aConnection connection: (NSConnection*)aConnection
{ {
NSDistantObject *new_proxy; NSDistantObject *new_proxy;
NSAssert([aConnection isValid], NSInternalInconsistencyException); NSAssert([aConnection isValid], NSInternalInconsistencyException);
if ((new_proxy = [aConnection localForTarget: anObject])) { if ((new_proxy = [aConnection localForObject: anObject]))
{
return new_proxy; return new_proxy;
} }
return [[[NSDistantObject alloc] initWithLocal: anObject return [[[NSDistantObject alloc] initWithLocal: anObject
connection: aConnection] autorelease]; connection: aConnection] autorelease];
} }
+ (NSDistantObject*) proxyWithTarget: anObject + (NSDistantObject*) proxyWithTarget: (gsu32)anObject
connection: (NSConnection*)aConnection connection: (NSConnection*)aConnection
{ {
NSDistantObject *new_proxy; NSDistantObject *new_proxy;
NSAssert([aConnection isValid], NSInternalInconsistencyException); NSAssert([aConnection isValid], NSInternalInconsistencyException);
if ((new_proxy = [aConnection proxyForTarget: anObject])) { if ((new_proxy = [aConnection proxyForTarget: anObject]))
{
return new_proxy; return new_proxy;
} }
return [[[NSDistantObject alloc] initWithTarget: anObject return [[[NSDistantObject alloc] initWithTarget: anObject
@ -91,7 +99,8 @@ enum
- (void) dealloc - (void) dealloc
{ {
if (_isLocal) { if (_object)
{
/* /*
* A proxy for local object retains it's target so that it * A proxy for local object retains it's target so that it
* will continue to exist as long as there is a remote * will continue to exist as long as there is a remote
@ -99,7 +108,8 @@ enum
*/ */
[_object release]; [_object release];
} }
else { else
{
/* /*
* A proxy retains it's connection so that the connection will * A proxy retains it's connection so that the connection will
* continue to exist as long as there is a somethig to use it. * continue to exist as long as there is a somethig to use it.
@ -110,17 +120,17 @@ enum
[super dealloc]; [super dealloc];
} }
- (void) encodeWithCoder: aRmc - (void) encodeWithCoder: (NSCoder*)aRmc
{ {
unsigned int proxy_target; gsu32 proxy_target;
unsigned char proxy_tag; gsu8 proxy_tag;
NSConnection *encoder_connection; NSConnection *encoder_connection;
if ([aRmc class] != [PortEncoder class]) if ([aRmc class] != [PortEncoder class])
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"NSDistantObject objects only encode with PortEncoder class"]; format: @"NSDistantObject objects only encode with PortEncoder class"];
encoder_connection = [aRmc connection]; encoder_connection = [(NSPortCoder*)aRmc connection];
NSAssert(encoder_connection, NSInternalInconsistencyException); NSAssert(encoder_connection, NSInternalInconsistencyException);
if (![encoder_connection isValid]) if (![encoder_connection isValid])
[NSException [NSException
@ -129,10 +139,12 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
@"You should request NSConnectionDidDieNotification's and\n" @"You should request NSConnectionDidDieNotification's and\n"
@"release all references to the proxy's of invalid Connections."]; @"release all references to the proxy's of invalid Connections."];
proxy_target = (unsigned int)_object; proxy_target = _handle;
if (encoder_connection == _connection) { if (encoder_connection == _connection)
if (_isLocal) { {
if (_object)
{
/* /*
* This proxy is a local to us, remote to other side. * This proxy is a local to us, remote to other side.
*/ */
@ -140,7 +152,7 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
if (debug_proxy) if (debug_proxy)
NSLog(@"Sending a proxy, will be remote 0x%x connection 0x%x\n", NSLog(@"Sending a proxy, will be remote 0x%x connection 0x%x\n",
(unsigned)_object, (unsigned)proxy_target,
(unsigned)_connection); (unsigned)_connection);
[aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) [aRmc encodeValueOfCType: @encode(typeof(proxy_tag))
@ -151,7 +163,8 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
at: &proxy_target at: &proxy_target
withName: @"Proxy target"]; withName: @"Proxy target"];
} }
else { else
{
/* /*
* This proxy is a local object on the other side. * This proxy is a local object on the other side.
*/ */
@ -159,7 +172,7 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
if (debug_proxy) if (debug_proxy)
NSLog(@"Sending a proxy, will be local 0x%x connection 0x%x\n", NSLog(@"Sending a proxy, will be local 0x%x connection 0x%x\n",
(unsigned)_object, (unsigned)proxy_target,
(unsigned)_connection); (unsigned)_connection);
[aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) [aRmc encodeValueOfCType: @encode(typeof(proxy_tag))
@ -171,7 +184,8 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
withName: @"Proxy target"]; withName: @"Proxy target"];
} }
} }
else { else
{
/* /*
* This proxy will still be remote on the other side * This proxy will still be remote on the other side
*/ */
@ -195,7 +209,7 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
*/ */
[aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) [aRmc encodeValueOfCType: @encode(typeof(proxy_tag))
at: &proxy_tag at: &proxy_tag
withName: @"Proxy is remote for both sender and receiver"]; withName: @"Proxy remote for both sender and receiver"];
[aRmc encodeValueOfCType: @encode(typeof(proxy_target)) [aRmc encodeValueOfCType: @encode(typeof(proxy_target))
at: &proxy_target at: &proxy_target
@ -216,19 +230,17 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
- (void) forwardInvocation: (NSInvocation*)anInvocation - (void) forwardInvocation: (NSInvocation*)anInvocation
{ {
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Not yet implemented '%s'", format: @"Not yet implemented '%s'", sel_get_name(_cmd)];
sel_get_name(_cmd)];
} }
- initWithCoder: coder - (id) initWithCoder: (NSCoder*)coder
{ {
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Not yet implemented '%s'", format: @"Not yet implemented '%s'", sel_get_name(_cmd)];
sel_get_name(_cmd)];
return nil; return nil;
} }
- initWithLocal:anObject connection: (NSConnection*)aConnection - (id) initWithLocal: (id)anObject connection: (NSConnection*)aConnection
{ {
NSDistantObject *new_proxy; NSDistantObject *new_proxy;
@ -238,12 +250,12 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
* If there already is a local proxy for this target/connection * If there already is a local proxy for this target/connection
* combination, don't create a new one, just return the old one. * combination, don't create a new one, just return the old one.
*/ */
if ((new_proxy = [aConnection localForTarget: anObject])) { if ((new_proxy = [aConnection localForObject: anObject]))
{
[self dealloc]; [self dealloc];
return [new_proxy retain]; return [new_proxy retain];
} }
_isLocal = YES;
_connection = aConnection; _connection = aConnection;
/* /*
@ -252,6 +264,10 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
*/ */
_object = [anObject retain]; _object = [anObject retain];
[handle_lock lock];
_handle = ++handle_counter;
[handle_lock unlock];
/* /*
* We register this object with the connection using it. * We register this object with the connection using it.
*/ */
@ -264,7 +280,7 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
return self; return self;
} }
- initWithTarget:anObject connection: (NSConnection*)aConnection - (id) initWithTarget: (gsu32)target connection: (NSConnection*)aConnection
{ {
NSDistantObject *new_proxy; NSDistantObject *new_proxy;
@ -274,13 +290,14 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
* If there already is a proxy for this target/connection combination, * If there already is a proxy for this target/connection combination,
* don't create a new one, just return the old one. * don't create a new one, just return the old one.
*/ */
if ((new_proxy = [aConnection proxyForTarget: anObject])) { if ((new_proxy = [aConnection proxyForTarget: target]))
{
[self dealloc]; [self dealloc];
return [new_proxy retain]; return [new_proxy retain];
} }
_isLocal = NO; _object = nil;
_object = anObject; _handle = target;
/* /*
* We retain our connection so it can't disappear while the app * We retain our connection so it can't disappear while the app
@ -302,28 +319,35 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector - (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
{ {
if (_isLocal) { if (_object)
{
return [_object methodSignatureForSelector: aSelector]; return [_object methodSignatureForSelector: aSelector];
} }
else { else
if (_protocol) { {
if (_protocol)
{
const char *types = 0; const char *types = 0;
struct objc_method_description* mth; struct objc_method_description* mth;
mth = [_protocol descriptionForInstanceMethod: aSelector]; mth = [_protocol descriptionForInstanceMethod: aSelector];
if (mth == 0) { if (mth == 0)
{
mth = [_protocol descriptionForClassMethod: aSelector]; mth = [_protocol descriptionForClassMethod: aSelector];
} }
if (mth != 0) { if (mth != 0)
{
types = mth->types; types = mth->types;
} }
if (types == 0) { if (types == 0)
{
return nil; return nil;
} }
return [NSMethodSignature signatureWithObjCTypes: types]; return [NSMethodSignature signatureWithObjCTypes: types];
} }
else { else
{
arglist_t args; arglist_t args;
/* /*
@ -342,8 +366,10 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
- (void) release - (void) release
{ {
if ([self retainCount] == 2) { if ([self retainCount] == 2)
if (_isLocal == NO) { {
if (_object == nil)
{
/* /*
* If the only thing retaining us after this release is our * If the only thing retaining us after this release is our
* connection we must be removed from the connection. * connection we must be removed from the connection.
@ -362,9 +388,9 @@ format: @"NSDistantObject objects only encode with PortEncoder class"];
@implementation NSDistantObject(GNUstepExtensions) @implementation NSDistantObject(GNUstepExtensions)
+ newForRemoteTarget: (unsigned)target connection: (NSConnection*)conn + newForRemoteTarget: (gsu32)target connection: (NSConnection*)conn
{ {
return [[NSDistantObject alloc] initWithTarget:(id)target connection:conn]; return [[NSDistantObject alloc] initWithTarget: target connection: conn];
} }
- awakeAfterUsingCoder: aDecoder - awakeAfterUsingCoder: aDecoder
@ -386,8 +412,8 @@ static inline BOOL class_is_kind_of (Class self, Class aClassObject)
+ newWithCoder: aRmc + newWithCoder: aRmc
{ {
unsigned char proxy_tag; gsu8 proxy_tag;
unsigned target; gsu32 target;
id decoder_connection; id decoder_connection;
if ([aRmc class] != [PortDecoder class]) if ([aRmc class] != [PortDecoder class])
@ -402,16 +428,13 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
at: &proxy_tag at: &proxy_tag
withName: NULL]; withName: NULL];
switch (proxy_tag) { switch (proxy_tag)
{
case PROXY_LOCAL_FOR_RECEIVER: case PROXY_LOCAL_FOR_RECEIVER:
/* /*
* This was a proxy on the other side of the connection, but * This was a proxy on the other side of the connection, but
* here it's local. * here it's local.
* Lookup the target address to ensure that it exists here. * Lookup the target handle to ensure that it exists here.
* Send [NSDistantObject +proxyWithLocal:connection:]; this will
* return the proxy object we already created for this target, or
* create a new proxy object if necessary.
* Return a retained copy of the local target object. * Return a retained copy of the local target object.
*/ */
[aRmc decodeValueOfCType: @encode(typeof(target)) [aRmc decodeValueOfCType: @encode(typeof(target))
@ -422,18 +445,21 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
NSLog(@"Receiving a proxy for local object 0x%x " NSLog(@"Receiving a proxy for local object 0x%x "
@"connection 0x%x\n", target, (unsigned)decoder_connection); @"connection 0x%x\n", target, (unsigned)decoder_connection);
if (![[decoder_connection class] includesLocalObject: (id)target]) if (![[decoder_connection class] includesLocalTarget: target])
[NSException raise: @"ProxyDecodedBadTarget" [NSException raise: @"ProxyDecodedBadTarget"
format: @"No local object with given address"]; format: @"No local object with given address"];
else
{ {
id local = [NSDistantObject proxyWithLocal: (id)target NSDistantObject *o;
connection: decoder_connection];
o = [decoder_connection includesLocalTarget: target];
if (debug_proxy) if (debug_proxy)
{
NSLog(@"Local object is 0x%x (0x%x)\n", NSLog(@"Local object is 0x%x (0x%x)\n",
(unsigned)local, (unsigned)[local targetForProxy]); (unsigned)o, (unsigned)[o localForProxy]);
return [[local targetForProxy] retain]; }
[self release];
return [[o localForProxy] retain];
} }
case PROXY_LOCAL_FOR_SENDER: case PROXY_LOCAL_FOR_SENDER:
@ -450,7 +476,7 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
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",
(unsigned)target, (unsigned)decoder_connection); (unsigned)target, (unsigned)decoder_connection);
return [[NSDistantObject proxyWithTarget: (id)target return [[NSDistantObject proxyWithTarget: target
connection: decoder_connection] retain]; connection: decoder_connection] retain];
case PROXY_REMOTE_FOR_BOTH: case PROXY_REMOTE_FOR_BOTH:
@ -516,10 +542,10 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
* remote system, we must tell the other end to retain its * remote system, we must tell the other end to retain its
* local object for our use. * local object for our use.
*/ */
if ([proxy_connection includesProxyForTarget: (id)target] == NO) if ([proxy_connection includesProxyForTarget: target] == NO)
[proxy_connection retainTarget: target]; [proxy_connection retainTarget: target];
result = [[NSDistantObject proxyWithTarget: (id)target result = [[NSDistantObject proxyWithTarget: target
connection: proxy_connection] retain]; connection: proxy_connection] retain];
return result; return result;
} }
@ -555,11 +581,16 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
#endif #endif
} }
- targetForProxy - (id) localForProxy
{ {
return _object; return _object;
} }
- (gsu32) targetForProxy
{
return _handle;
}
- forward: (SEL)aSel :(arglist_t)frame - forward: (SEL)aSel :(arglist_t)frame
{ {
if (debug_proxy) if (debug_proxy)