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];
id counter; gsu32 target = [anObj targetForProxy];
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]; {
NSMapInsert(all_connections_local_targets, (void*)local, counter); counter = [ConnectionLocalCounter new];
[counter release]; NSMapInsert(all_connections_local_objects, (void*)object, counter);
NSMapInsert(all_connections_local_targets, (void*)target, counter);
[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,127 +1840,134 @@ static int messages_received_count;
- (void) removeLocalObject: anObj - (void) removeLocalObject: anObj
{ {
id counter; NSDistantObject *prox = NSMapGet(local_objects, (void*)anObj);
unsigned val = 0; gsu32 target = [prox targetForProxy];
id counter;
unsigned val = 0;
[proxiesHashGate lock]; [proxiesHashGate lock];
/* /*
* 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]; {
if ((val = [counter value]) == 0) { [counter decrement];
NSDistantObject *prox = NSMapGet(local_targets, (void*)anObj); if ((val = [counter value]) == 0)
{
NSMapRemove(all_connections_local_targets, (void*)anObj); NSMapRemove(all_connections_local_objects, (void*)anObj);
/* NSMapRemove(all_connections_local_targets, (void*)target);
* If this proxy has been vended onwards by another process, we /*
* need to keep a reference to the local object around for a * If this proxy has been vended onwards by another process, we
* while in case that other process needs it. * need to keep a reference to the local object around for a
*/ * while in case that other process needs it.
if ([prox isVended]) { */
id item; if ([prox isVended])
if (timer == nil) { {
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 id item;
target: [NSConnection class] if (timer == nil)
{
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
target: [NSConnection class]
selector: @selector(_timeout:) selector: @selector(_timeout:)
userInfo: nil userInfo: nil
repeats: YES]; repeats: YES];
} }
item = [CachedLocalObject itemWithObject: anObj time: 30]; item = [CachedLocalObject itemWithObject: anObj time: 30];
NSMapInsert(all_connections_local_cached, anObj, item); NSMapInsert(all_connections_local_cached, anObj, item);
} }
} }
} }
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",
(unsigned)anObj, (unsigned) self, val); (unsigned)anObj, (unsigned) self, val);
[proxiesHashGate unlock]; [proxiesHashGate unlock];
} }
- (void) _release_targets: (NSDistantObject**)list count:(unsigned int)number - (void) _release_targets: (NSDistantObject**)list count:(unsigned int)number
{ {
NS_DURING NS_DURING
{ {
/* /*
* Tell the remote app that it can release its local objects * Tell the remote app that it can release its local objects
* for the targets in the specified list since we don't have * for the targets in the specified list since we don't have
* proxies for them any more. * proxies for them any more.
*/ */
if (receive_port && is_valid && number > 0) { if (receive_port && is_valid && number > 0) {
id op; id op;
unsigned int i; unsigned int i;
op = [[self encodingClass] op = [[self encodingClass]
newForWritingWithConnection: self newForWritingWithConnection: self
sequenceNumber: [self _newMsgNumber] sequenceNumber: [self _newMsgNumber]
identifier: PROXY_RELEASE]; identifier: PROXY_RELEASE];
[op encodeValueOfCType: @encode(typeof(number)) [op encodeValueOfCType: @encode(typeof(number))
at: &number at: &number
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))
at: &target at: &target
withName: NULL]; withName: NULL];
[op encodeValueOfCType: @encode(char) [op encodeValueOfCType: @encode(char)
at: &vended at: &vended
withName: NULL]; withName: NULL];
} }
[op dismiss]; [op dismiss];
} }
} }
NS_HANDLER NS_HANDLER
{ {
if (debug_connection) if (debug_connection)
NSLog(@"failed to release targets - %@\n", [localException name]); NSLog(@"failed to release targets - %@\n", [localException name]);
} }
NS_ENDHANDLER NS_ENDHANDLER
} }
- (void) retainTarget: (unsigned int)target - (void) retainTarget: (gsu32)target
{ {
NS_DURING NS_DURING
{ {
/* /*
* 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; {
unsigned int i; id op;
int seq_num = [self _newMsgNumber]; unsigned int i;
int seq_num = [self _newMsgNumber];
op = [[self encodingClass] op = [[self encodingClass]
newForWritingWithConnection: self newForWritingWithConnection: self
sequenceNumber: seq_num sequenceNumber: seq_num
identifier: PROXY_RETAIN]; identifier: PROXY_RETAIN];
[op encodeValueOfCType: @encode(typeof(target)) [op encodeValueOfCType: @encode(typeof(target))
at: &target at: &target
withName: NULL]; withName: NULL];
[op dismiss]; [op dismiss];
} }
} }
NS_HANDLER NS_HANDLER
{ {
if (debug_connection) if (debug_connection)
NSLog(@"failed to retain target - %@\n", [localException name]); NSLog(@"failed to retain target - %@\n", [localException name]);
} }
NS_ENDHANDLER NS_ENDHANDLER
} }
- (void) removeProxy: (NSDistantObject*)aProxy - (void) removeProxy: (NSDistantObject*)aProxy
@ -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>
@ -36,7 +37,7 @@ static int debug_proxy;
@implementation NSDistantObject (Debug) @implementation NSDistantObject (Debug)
+ (void) setDebug: (int)val + (void) setDebug: (int)val
{ {
debug_proxy = val; debug_proxy = val;
} }
@end @end
@ -52,161 +53,174 @@ 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
connection: aConnection] autorelease]; connection: aConnection] autorelease];
} }
- (NSConnection*) connectionForProxy - (NSConnection*) connectionForProxy
{ {
return _connection; return _connection;
} }
- (void) dealloc - (void) dealloc
{ {
if (_isLocal) { if (_object)
/* {
* A proxy for local object retains it's target so that it /*
* will continue to exist as long as there is a remote * A proxy for local object retains it's target so that it
* application using it - so we release the object here. * will continue to exist as long as there is a remote
*/ * application using it - so we release the object here.
[_object release]; */
[_object release];
} }
else { else
/* {
* A proxy retains it's connection so that the connection will /*
* continue to exist as long as there is a somethig to use it. * A proxy retains it's connection so that the connection will
* So we release our reference to the connection here. * continue to exist as long as there is a somethig to use it.
*/ * So we release our reference to the connection here.
[_connection release]; */
[_connection release];
} }
[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
raise: NSGenericException raise: NSGenericException
format: @"Trying to encode to an invalid Connection.\n" format: @"Trying to encode to an invalid Connection.\n"
@"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. {
*/ /*
proxy_tag = PROXY_LOCAL_FOR_SENDER; * This proxy is a local to us, remote to other side.
*/
proxy_tag = PROXY_LOCAL_FOR_SENDER;
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))
at: &proxy_tag at: &proxy_tag
withName: @"Proxy is local for sender"]; withName: @"Proxy is local for sender"];
[aRmc encodeValueOfCType: @encode(typeof(proxy_target)) [aRmc encodeValueOfCType: @encode(typeof(proxy_target))
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.
proxy_tag = PROXY_LOCAL_FOR_RECEIVER; */
proxy_tag = PROXY_LOCAL_FOR_RECEIVER;
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))
at: &proxy_tag at: &proxy_tag
withName: @"Proxy is local for receiver"]; withName: @"Proxy is local for receiver"];
[aRmc encodeValueOfCType: @encode(typeof(proxy_target)) [aRmc encodeValueOfCType: @encode(typeof(proxy_target))
at: &proxy_target at: &proxy_target
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
NSPort *proxy_connection_out_port = [_connection sendPort]; */
NSPort *proxy_connection_out_port = [_connection sendPort];
NSAssert(proxy_connection_out_port, NSInternalInconsistencyException); NSAssert(proxy_connection_out_port, NSInternalInconsistencyException);
NSAssert([proxy_connection_out_port isValid], NSInternalInconsistencyException); NSAssert([proxy_connection_out_port isValid], NSInternalInconsistencyException);
NSAssert(proxy_connection_out_port != [encoder_connection sendPort], NSInternalInconsistencyException); NSAssert(proxy_connection_out_port != [encoder_connection sendPort], NSInternalInconsistencyException);
proxy_tag = PROXY_REMOTE_FOR_BOTH; proxy_tag = PROXY_REMOTE_FOR_BOTH;
if (debug_proxy) if (debug_proxy)
NSLog(@"Sending triangle-connection proxy 0x%x " NSLog(@"Sending triangle-connection proxy 0x%x "
@"proxy-conn 0x%x to-conn 0x%x\n", @"proxy-conn 0x%x to-conn 0x%x\n",
(unsigned)_object, (unsigned)_object,
(unsigned)_connection, (unsigned)encoder_connection); (unsigned)_connection, (unsigned)encoder_connection);
/* /*
* It's remote here, so we need to tell other side where to form * It's remote here, so we need to tell other side where to form
* triangle connection to * triangle connection to
*/ */
[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
withName: @"Proxy target"]; withName: @"Proxy target"];
[aRmc encodeBycopyObject: proxy_connection_out_port [aRmc encodeBycopyObject: proxy_connection_out_port
withName: @"Proxy outPort"]; withName: @"Proxy outPort"];
/* /*
* Make a note that we have passed this on to another process. * Make a note that we have passed this on to another process.
*/ */
_isVended = YES; _isVended = YES;
} }
} }
@ -215,203 +229,212 @@ 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;
NSAssert([aConnection isValid], NSInternalInconsistencyException); NSAssert([aConnection isValid], NSInternalInconsistencyException);
/* /*
* 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]; {
return [new_proxy retain]; [self dealloc];
return [new_proxy retain];
} }
_isLocal = YES; _connection = aConnection;
_connection = aConnection;
/* /*
* We retain our target object so it can't disappear while a remote * We retain our target object so it can't disappear while a remote
* application wants to use it. * application wants to use it.
*/ */
_object = [anObject retain]; _object = [anObject retain];
/* [handle_lock lock];
* We register this object with the connection using it. _handle = ++handle_counter;
*/ [handle_lock unlock];
[_connection addLocalObject: self];
if (debug_proxy) /*
NSLog(@"Created new local=0x%x object 0x%x connection 0x%x\n", * We register this object with the connection using it.
*/
[_connection addLocalObject: self];
if (debug_proxy)
NSLog(@"Created new local=0x%x object 0x%x connection 0x%x\n",
(unsigned)self, (unsigned)_object, (unsigned)_connection); (unsigned)self, (unsigned)_object, (unsigned)_connection);
return self; return self;
} }
- initWithTarget:anObject connection: (NSConnection*)aConnection - (id) initWithTarget: (gsu32)target connection: (NSConnection*)aConnection
{ {
NSDistantObject *new_proxy; NSDistantObject *new_proxy;
NSAssert([aConnection isValid], NSInternalInconsistencyException); NSAssert([aConnection isValid], NSInternalInconsistencyException);
/* /*
* 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]; {
return [new_proxy retain]; [self dealloc];
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
* may want to use it. * may want to use it.
*/ */
_connection = [aConnection retain]; _connection = [aConnection retain];
/* /*
* We register this object with the connection using it. * We register this object with the connection using it.
*/ */
[_connection addProxy: self]; [_connection addProxy: self];
if (debug_proxy) if (debug_proxy)
NSLog(@"Created new proxy=0x%x object 0x%x connection 0x%x\n", NSLog(@"Created new proxy=0x%x object 0x%x connection 0x%x\n",
(unsigned)self, (unsigned)_object, (unsigned)_connection); (unsigned)self, (unsigned)_object, (unsigned)_connection);
return self; return self;
} }
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector - (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
{ {
if (_isLocal) { if (_object)
return [_object methodSignatureForSelector: aSelector]; {
return [_object methodSignatureForSelector: aSelector];
} }
else { else
if (_protocol) { {
const char *types = 0; if (_protocol)
{
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;
/* /*
* No protocol - so try forwarding the message. * No protocol - so try forwarding the message.
*/ */
args = __builtin_apply_args(); args = __builtin_apply_args();
__builtin_return([self forward: _cmd : args]); __builtin_return([self forward: _cmd : args]);
} }
} }
} }
- (void) setProtocolForProxy: (Protocol*)aProtocol - (void) setProtocolForProxy: (Protocol*)aProtocol
{ {
_protocol = aProtocol; _protocol = aProtocol;
} }
- (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 {
* connection we must be removed from the connection. /*
* Bracket that removal with a retain and release to ensure * If the only thing retaining us after this release is our
* that we don't have problems when the connection releases us. * connection we must be removed from the connection.
*/ * Bracket that removal with a retain and release to ensure
[super retain]; * that we don't have problems when the connection releases us.
[_connection removeProxy:self]; */
[super release]; [super retain];
[_connection removeProxy: self];
[super release];
} }
} }
[super release]; [super release];
} }
@end @end
@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
{ {
return self; return self;
} }
static inline BOOL class_is_kind_of (Class self, Class aClassObject) static inline BOOL class_is_kind_of (Class self, Class aClassObject)
{ {
Class class; Class class;
for (class = self; class!=Nil; class = class_get_super_class(class)) for (class = self; class!=Nil; class = class_get_super_class(class))
if (class==aClassObject) if (class==aClassObject)
return YES; return YES;
return NO; return NO;
} }
+ 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])
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"NSDistantObject objects only decode with PortDecoder class"]; format: @"NSDistantObject objects only decode with PortDecoder class"];
decoder_connection = [aRmc connection]; decoder_connection = [aRmc connection];
NSAssert(decoder_connection, NSInternalInconsistencyException); NSAssert(decoder_connection, NSInternalInconsistencyException);
/* First get the tag, so we know what values need to be decoded. */ /* First get the tag, so we know what values need to be decoded. */
[aRmc decodeValueOfCType: @encode(typeof(proxy_tag)) [aRmc decodeValueOfCType: @encode(typeof(proxy_tag))
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))
@ -419,24 +442,27 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
withName: NULL]; withName: NULL];
if (debug_proxy) if (debug_proxy)
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
{
NSDistantObject *o;
{ o = [decoder_connection includesLocalTarget: target];
id local = [NSDistantObject proxyWithLocal: (id)target if (debug_proxy)
connection: decoder_connection]; {
NSLog(@"Local object is 0x%x (0x%x)\n",
(unsigned)o, (unsigned)[o localForProxy]);
}
[self release];
return [[o localForProxy] retain];
}
if (debug_proxy) case PROXY_LOCAL_FOR_SENDER:
NSLog(@"Local object is 0x%x (0x%x)\n",
(unsigned)local, (unsigned)[local targetForProxy]);
return [[local targetForProxy] retain];
}
case PROXY_LOCAL_FOR_SENDER:
/* /*
* This was a local object on the other side of the connection, * This was a local object on the other side of the connection,
* but here it's a proxy object. Get the target address, and * but here it's a proxy object. Get the target address, and
@ -444,16 +470,16 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
* return the proxy object we already created for this target, or * return the proxy object we already created for this target, or
* create a new proxy object if necessary. * create a new proxy object if necessary.
*/ */
[aRmc decodeValueOfCType: @encode(typeof(target)) [aRmc decodeValueOfCType: @encode(typeof(target))
at: &target at: &target
withName: NULL]; withName: NULL];
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:
/* /*
* This was a proxy on the other side of the connection, and it * 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 * will be a proxy on this side too; that is, the local version
@ -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,41 +581,46 @@ 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)
NSLog(@"NSDistantObject forwarding %s\n", sel_get_name(aSel)); NSLog(@"NSDistantObject forwarding %s\n", sel_get_name(aSel));
if (![_connection isValid]) if (![_connection isValid])
[NSException [NSException
raise: NSGenericException raise: NSGenericException
format: @"Trying to send message to an invalid Proxy.\n" format: @"Trying to send message to an invalid Proxy.\n"
@"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."];
return [_connection forwardForProxy: self return [_connection forwardForProxy: self
selector: aSel selector: aSel
argFrame: frame]; argFrame: frame];
} }
- classForCoder - classForCoder
{ {
return object_get_class (self); return object_get_class (self);
} }
- classForPortCoder - classForPortCoder
{ {
return object_get_class (self); return object_get_class (self);
} }
- replacementObjectForCoder:(NSCoder*)aCoder - replacementObjectForCoder:(NSCoder*)aCoder
{ {
return self; return self;
} }
- replacementObjectForPortCoder:(NSPortCoder*)aCoder - replacementObjectForPortCoder:(NSPortCoder*)aCoder
@ -621,16 +652,16 @@ format: @"NSDistantObject objects only decode with PortDecoder class"];
- (Class) classForPortCoder - (Class) classForPortCoder
{ {
return [self class]; return [self class];
} }
- replacementObjectForPortCoder: (NSPortCoder*)aRmc; - replacementObjectForPortCoder: (NSPortCoder*)aRmc;
{ {
if ([aRmc isBycopy]) if ([aRmc isBycopy])
return self; return self;
else else
return [NSDistantObject proxyWithLocal: self return [NSDistantObject proxyWithLocal: self
connection: [aRmc connection]]; connection: [aRmc connection]];
} }
@end @end