diff --git a/ChangeLog b/ChangeLog index 76b40c7de..b42be460a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sun Jan 24 8:50:00 1999 Richard Frith-Macdonald + + * 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 * src/NSUserDefaults.m: Fixed to update periodically from disk and diff --git a/Headers/gnustep/base/DistributedObjects.h b/Headers/gnustep/base/DistributedObjects.h index 6cfd96351..22c8f0476 100644 --- a/Headers/gnustep/base/DistributedObjects.h +++ b/Headers/gnustep/base/DistributedObjects.h @@ -74,9 +74,12 @@ enum { + (NSConnection*) connectionByInPort: (NSPort*)ip outPort: (NSPort*)op; + (NSConnection*) connectionByOutPort: (NSPort*)op; -- (NSDistantObject*) localForTarget: (void*)target; -- (NSDistantObject*) proxyForTarget: (void*)target; -- (void) retainTarget: (unsigned)target; ++ (NSDistantObject*) includesLocalTarget: (gsu32)target; +- (NSDistantObject*) includesLocalTarget: (gsu32)target; +- (NSDistantObject*) localForObject: (id)object; +- (NSDistantObject*) localForTarget: (gsu32)target; +- (NSDistantObject*) proxyForTarget: (gsu32)target; +- (void) retainTarget: (gsu32)target; - (void) setNotOwned; @end diff --git a/Headers/gnustep/base/NSConnection.h b/Headers/gnustep/base/NSConnection.h index 26c117d26..6faa1c53f 100644 --- a/Headers/gnustep/base/NSConnection.h +++ b/Headers/gnustep/base/NSConnection.h @@ -70,6 +70,7 @@ extern NSString *NSConnectionProxyCount; /* Objects received */ unsigned req_in_count; unsigned rep_out_count; unsigned rep_in_count; + NSMapTable *local_objects; NSMapTable *local_targets; NSMapTable *remote_proxies; NSTimeInterval reply_timeout; @@ -220,7 +221,7 @@ extern NSString *NSConnectionProxyCount; /* Objects received */ /* Only subclassers and power-users need worry about these */ - (void) addProxy: (NSDistantObject*)aProxy; -- (id) includesProxyForTarget: (void*)target; +- (id) includesProxyForTarget: (gsu32)target; - (void) removeProxy: (NSDistantObject*)aProxy; // It seems to be a non pure-OPENSTEP definition... diff --git a/Headers/gnustep/base/NSDistantObject.h b/Headers/gnustep/base/NSDistantObject.h index c7b80f04e..eaec90b73 100644 --- a/Headers/gnustep/base/NSDistantObject.h +++ b/Headers/gnustep/base/NSDistantObject.h @@ -34,33 +34,39 @@ @private NSConnection *_connection; id _object; - BOOL _isLocal; + gsu32 _handle; BOOL _isVended; Protocol *_protocol; } -+ (NSDistantObject*) proxyWithLocal: anObject ++ (NSDistantObject*) proxyWithLocal: (id)anObject 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; - (NSConnection*) connectionForProxy; -- initWithLocal:anObject connection: (NSConnection*)aConnection; -- initWithTarget:anObject connection: (NSConnection*)aConnection; +- (id) initWithLocal: (id)anObject connection: (NSConnection*)aConnection; +- (id) initWithTarget: (gsu32)anObject connection: (NSConnection*)aConnection; - (void) setProtocolForProxy: (Protocol*)aProtocol; @end @interface NSDistantObject(GNUstepExtensions) -+ newForRemoteTarget: (unsigned)target connection: (NSConnection*)conn; ++ newForRemoteTarget: (gsu32)target connection: (NSConnection*)conn; - awakeAfterUsingCoder: aDecoder; - classForPortCoder; + newWithCoder: aRmc; - (const char *) selectorTypeForProxy: (SEL)selector; - forward: (SEL)aSel :(arglist_t)frame; -- targetForProxy; +- (id) localForProxy; +- (gsu32) targetForProxy; @end #endif /* __NSDistantObject_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Source/NSConnection.m b/Source/NSConnection.m index 7b3f43787..b0e330b9b 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -254,6 +254,7 @@ static NSLock *root_object_dictionary_gate; 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_cached = NULL; @@ -327,9 +328,12 @@ static int messages_received_count; connection_array = [[NSMutableArray alloc] initWithCapacity:8]; connection_array_gate = [NSLock new]; /* xxx When NSHashTable's are working, change this. */ - all_connections_local_targets = + all_connections_local_objects = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSObjectMapValueCallBacks, 0); + all_connections_local_targets = + NSCreateMapTable (NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); all_connections_local_cached = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSObjectMapValueCallBacks, 0); @@ -431,6 +435,7 @@ static int messages_received_count; [proxiesHashGate lock]; NSFreeMapTable (remote_proxies); + NSFreeMapTable (local_objects); NSFreeMapTable (local_targets); NSFreeMapTable (incoming_xref_2_const_ptr); NSFreeMapTable (outgoing_const_ptr_2_xref); @@ -522,7 +527,7 @@ static int messages_received_count; targets = [NSAllMapTableValues(local_targets) retain]; for (i = 0; i < [targets count]; i++) { - id t = [[targets objectAtIndex:i] targetForProxy]; + id t = [[targets objectAtIndex:i] localForProxy]; [self removeLocalObject:t]; } @@ -925,10 +930,15 @@ static int messages_received_count; /* This maps (void*)obj to (id)obj. The obj's are retained. We use this instead of an NSHashTable because we only care about the object's address, and don't want to send the -hash message to it. */ - newConn->local_targets = + newConn->local_objects = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSObjectMapValueCallBacks, 0); + /* This maps handles for local objects to their local proxies. */ + newConn->local_targets = + NSCreateMapTable (NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + /* This maps [proxy targetForProxy] to proxy. The proxy's are retained. */ newConn->remote_proxies = NSCreateMapTable (NSIntMapKeyCallBacks, @@ -1437,7 +1447,7 @@ static int messages_received_count; withName: NULL]; for (pos = 0; pos < count; pos++) { - unsigned int target; + gsu32 target; char vended; NSDistantObject *prox; @@ -1463,7 +1473,7 @@ static int messages_received_count; - (void) _service_retain: rmc forConnection: receiving_connection { - unsigned int target; + gsu32 target; NSParameterAssert (is_valid); @@ -1508,7 +1518,7 @@ static int messages_received_count; [rmc dismiss]; } -- (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target +- (const char *) typeForSelector: (SEL)sel remoteTarget: (gsu32)target { id op, ip; char *type = 0; @@ -1524,7 +1534,7 @@ static int messages_received_count; [op encodeValueOfObjCType:":" at:&sel withName:NULL]; - [op encodeValueOfCType:@encode(unsigned) + [op encodeValueOfCType:@encode(gsu32) at:&target withName:NULL]; [op dismiss]; @@ -1539,7 +1549,9 @@ static int messages_received_count; - (void) _service_typeForSelector: rmc { NSPortCoder* op; - unsigned target; + gsu32 target; + NSDistantObject *p; + id o; SEL sel; const char *type; struct objc_method* m; @@ -1555,12 +1567,15 @@ static int messages_received_count; [rmc decodeValueOfObjCType:":" at:&sel withName:NULL]; - [rmc decodeValueOfCType:@encode(unsigned) + [rmc decodeValueOfCType:@encode(gsu32) at:&target withName:NULL]; + p = [self includesLocalTarget: target]; + o = [p localForProxy]; + /* xxx We should make sure that TARGET is a valid object. */ /* 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 version of the method types that has the type qualifiers in it. Search the protocols list. */ @@ -1764,47 +1779,52 @@ static int messages_received_count; /* Managing objects and proxies. */ - (void) addLocalObject: anObj { - id local = [anObj targetForProxy]; - id counter; + id object = [anObj localForProxy]; + gsu32 target = [anObj targetForProxy]; + id counter; - NSParameterAssert (is_valid); - [proxiesHashGate lock]; - /* xxx Do we need to check to make sure it's not already there? */ - /* This retains anObj. */ - NSMapInsert(local_targets, (void*)local, anObj); + NSParameterAssert (is_valid); + [proxiesHashGate lock]; + /* xxx Do we need to check to make sure it's not already there? */ + /* This retains anObj. */ + NSMapInsert(local_objects, (void*)object, anObj); + NSMapInsert(local_targets, (void*)target, anObj); - /* - * Keep track of local objects accross all connections. - */ - counter = NSMapGet(all_connections_local_targets, (void*)local); - if (counter) { - [counter increment]; + /* + * Keep track of local objects accross all connections. + */ + counter = NSMapGet(all_connections_local_objects, (void*)object); + if (counter) + { + [counter increment]; } - else { - counter = [ConnectionLocalCounter new]; - NSMapInsert(all_connections_local_targets, (void*)local, counter); - [counter release]; + else + { + counter = [ConnectionLocalCounter new]; + NSMapInsert(all_connections_local_objects, (void*)object, counter); + NSMapInsert(all_connections_local_targets, (void*)target, counter); + [counter release]; } - if (debug_connection > 2) - NSLog(@"add local object (0x%x) to connection (0x%x) (ref %d)\n", - (unsigned)local, (unsigned) self, [counter value]); - [proxiesHashGate unlock]; + if (debug_connection > 2) + NSLog(@"add local object (0x%x) to connection (0x%x) (ref %d)\n", + (unsigned)object, (unsigned) self, [counter value]); + [proxiesHashGate unlock]; } -- (NSDistantObject*) localForTarget: (void*)target +- (NSDistantObject*) localForObject: (id)object { NSDistantObject *p; /* Don't assert (is_valid); */ [proxiesHashGate lock]; - p = NSMapGet (local_targets, target); + p = NSMapGet (local_objects, (void*)object); [proxiesHashGate unlock]; NSParameterAssert(!p || [p connectionForProxy] == self); return p; } /* This should get called whenever an object free's itself */ -+ (void) removeLocalObject: anObj ++ (void) removeLocalObject: (id)anObj { id c; int i, count = [connection_array count]; @@ -1820,127 +1840,134 @@ static int messages_received_count; - (void) removeLocalObject: anObj { - id counter; - unsigned val = 0; + NSDistantObject *prox = NSMapGet(local_objects, (void*)anObj); + gsu32 target = [prox targetForProxy]; + id counter; + unsigned val = 0; - [proxiesHashGate lock]; + [proxiesHashGate lock]; - /* - * If all references to a local proxy have gone - remove the - * global reference as well. - */ - counter = NSMapGet(all_connections_local_targets, (void*)anObj); - if (counter) { - [counter decrement]; - if ((val = [counter value]) == 0) { - NSDistantObject *prox = NSMapGet(local_targets, (void*)anObj); - - NSMapRemove(all_connections_local_targets, (void*)anObj); - /* - * If this proxy has been vended onwards by another process, we - * 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 (timer == nil) { - timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 - target: [NSConnection class] + /* + * If all references to a local proxy have gone - remove the + * global reference as well. + */ + counter = NSMapGet(all_connections_local_objects, (void*)anObj); + if (counter) + { + [counter decrement]; + if ((val = [counter value]) == 0) + { + 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 + * while in case that other process needs it. + */ + if ([prox isVended]) + { + id item; + if (timer == nil) + { + timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 + target: [NSConnection class] selector: @selector(_timeout:) userInfo: nil repeats: YES]; } - item = [CachedLocalObject itemWithObject: anObj time: 30]; - NSMapInsert(all_connections_local_cached, anObj, item); + item = [CachedLocalObject itemWithObject: anObj time: 30]; + 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) - NSLog(@"remove local object (0x%x) to connection (0x%x) (ref %d)\n", + if (debug_connection > 2) + NSLog(@"remove local object (0x%x) to connection (0x%x) (ref %d)\n", (unsigned)anObj, (unsigned) self, val); - [proxiesHashGate unlock]; + [proxiesHashGate unlock]; } - (void) _release_targets: (NSDistantObject**)list count:(unsigned int)number { - NS_DURING + NS_DURING { - /* - * Tell the remote app that it can release its local objects - * for the targets in the specified list since we don't have - * proxies for them any more. - */ - if (receive_port && is_valid && number > 0) { - id op; - unsigned int i; + /* + * Tell the remote app that it can release its local objects + * for the targets in the specified list since we don't have + * proxies for them any more. + */ + if (receive_port && is_valid && number > 0) { + id op; + unsigned int i; - op = [[self encodingClass] - newForWritingWithConnection: self - sequenceNumber: [self _newMsgNumber] - identifier: PROXY_RELEASE]; + op = [[self encodingClass] + newForWritingWithConnection: self + sequenceNumber: [self _newMsgNumber] + identifier: PROXY_RELEASE]; - [op encodeValueOfCType: @encode(typeof(number)) - at: &number - withName: NULL]; + [op encodeValueOfCType: @encode(typeof(number)) + at: &number + withName: NULL]; - for (i = 0; i < number; i++) { - unsigned target = (unsigned)[list[i] targetForProxy]; - char vended = [list[i] isVended]; + for (i = 0; i < number; i++) { + gsu32 target = [list[i] targetForProxy]; + char vended = [list[i] isVended]; - [op encodeValueOfCType: @encode(typeof(target)) - at: &target - withName: NULL]; - [op encodeValueOfCType: @encode(char) - at: &vended - withName: NULL]; - } + [op encodeValueOfCType: @encode(typeof(target)) + at: &target + withName: NULL]; + [op encodeValueOfCType: @encode(char) + at: &vended + withName: NULL]; + } - [op dismiss]; - } + [op dismiss]; + } } - NS_HANDLER + NS_HANDLER { if (debug_connection) 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 - * for the target on this connection. - */ - if (receive_port && is_valid) { - id op; - unsigned int i; - int seq_num = [self _newMsgNumber]; + /* + * Tell the remote app that it must retain the local object + * for the target on this connection. + */ + if (receive_port && is_valid) + { + id op; + unsigned int i; + int seq_num = [self _newMsgNumber]; - op = [[self encodingClass] - newForWritingWithConnection: self - sequenceNumber: seq_num - identifier: PROXY_RETAIN]; + op = [[self encodingClass] + newForWritingWithConnection: self + sequenceNumber: seq_num + identifier: PROXY_RETAIN]; - [op encodeValueOfCType: @encode(typeof(target)) - at: &target - withName: NULL]; + [op encodeValueOfCType: @encode(typeof(target)) + at: &target + withName: NULL]; - [op dismiss]; + [op dismiss]; } } - NS_HANDLER + NS_HANDLER { if (debug_connection) NSLog(@"failed to retain target - %@\n", [localException name]); } - NS_ENDHANDLER + NS_ENDHANDLER } - (void) removeProxy: (NSDistantObject*)aProxy @@ -1966,7 +1993,7 @@ static int messages_received_count; /* Don't assert (is_valid); */ [proxiesHashGate lock]; - c = NSAllMapTableValues (local_targets); + c = NSAllMapTableValues (local_objects); [proxiesHashGate unlock]; return c; } @@ -1982,13 +2009,13 @@ static int messages_received_count; return c; } -- (NSDistantObject*) proxyForTarget: (void*)target +- (NSDistantObject*) proxyForTarget: (gsu32)target { NSDistantObject *p; /* Don't assert (is_valid); */ [proxiesHashGate lock]; - p = NSMapGet (remote_proxies, target); + p = NSMapGet (remote_proxies, (void*)target); [proxiesHashGate unlock]; NSParameterAssert(!p || [p connectionForProxy] == self); return p; @@ -2009,7 +2036,7 @@ static int messages_received_count; [proxiesHashGate unlock]; } -- (id) includesProxyForTarget: (void*)target +- (id) includesProxyForTarget: (gsu32)target { NSDistantObject *ret; @@ -2020,13 +2047,24 @@ static int messages_received_count; return ret; } -- (id) includesLocalObject: anObj +- (id) includesLocalObject: (id)anObj { NSDistantObject* ret; /* Don't assert (is_valid); */ [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]; return ret; } @@ -2035,9 +2073,9 @@ static int messages_received_count; 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 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. */ -+ (id) includesLocalObject: anObj ++ (id) includesLocalTarget: (gsu32)anObj { id ret; diff --git a/Source/NSDistantObject.m b/Source/NSDistantObject.m index 868a72c54..892b07391 100644 --- a/Source/NSDistantObject.m +++ b/Source/NSDistantObject.m @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -36,7 +37,7 @@ static int debug_proxy; @implementation NSDistantObject (Debug) + (void) setDebug: (int)val { - debug_proxy = val; + debug_proxy = val; } @end @@ -52,161 +53,174 @@ enum PROXY_REMOTE_FOR_BOTH }; +static gsu32 handle_counter = 0; +static NSRecursiveLock *handle_lock = nil; + (void) initialize { - return; + if (self == [NSDistantObject class]) + { + handle_lock = [NSRecursiveLock new]; + } } -+ (NSDistantObject*) proxyWithLocal: anObject ++ (NSDistantObject*) proxyWithLocal: (id)anObject connection: (NSConnection*)aConnection { - NSDistantObject *new_proxy; + NSDistantObject *new_proxy; - NSAssert([aConnection isValid], NSInternalInconsistencyException); - if ((new_proxy = [aConnection localForTarget: anObject])) { - return new_proxy; + NSAssert([aConnection isValid], NSInternalInconsistencyException); + if ((new_proxy = [aConnection localForObject: anObject])) + { + return new_proxy; } - return [[[NSDistantObject alloc] initWithLocal: anObject - connection: aConnection] autorelease]; + return [[[NSDistantObject alloc] initWithLocal: anObject + connection: aConnection] autorelease]; } -+ (NSDistantObject*) proxyWithTarget: anObject ++ (NSDistantObject*) proxyWithTarget: (gsu32)anObject connection: (NSConnection*)aConnection { - NSDistantObject *new_proxy; + NSDistantObject *new_proxy; - NSAssert([aConnection isValid], NSInternalInconsistencyException); - if ((new_proxy = [aConnection proxyForTarget: anObject])) { - return new_proxy; + NSAssert([aConnection isValid], NSInternalInconsistencyException); + if ((new_proxy = [aConnection proxyForTarget: anObject])) + { + return new_proxy; } - return [[[NSDistantObject alloc] initWithTarget: anObject - connection: aConnection] autorelease]; + return [[[NSDistantObject alloc] initWithTarget: anObject + connection: aConnection] autorelease]; } - (NSConnection*) connectionForProxy { - return _connection; + return _connection; } - (void) dealloc { - if (_isLocal) { - /* - * A proxy for local object retains it's target so that it - * will continue to exist as long as there is a remote - * application using it - so we release the object here. - */ - [_object release]; + 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 + * application using it - so we release the object here. + */ + [_object release]; } - 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. - * So we release our reference to the connection here. - */ - [_connection release]; + 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. + * So we release our reference to the connection here. + */ + [_connection release]; } - [super dealloc]; + [super dealloc]; } -- (void) encodeWithCoder: aRmc +- (void) encodeWithCoder: (NSCoder*)aRmc { - unsigned int proxy_target; - unsigned char proxy_tag; - NSConnection *encoder_connection; + gsu32 proxy_target; + gsu8 proxy_tag; + NSConnection *encoder_connection; - if ([aRmc class] != [PortEncoder class]) - [NSException raise: NSGenericException + if ([aRmc class] != [PortEncoder class]) + [NSException raise: NSGenericException format: @"NSDistantObject objects only encode with PortEncoder class"]; - encoder_connection = [aRmc connection]; - NSAssert(encoder_connection, NSInternalInconsistencyException); - if (![encoder_connection isValid]) - [NSException + encoder_connection = [(NSPortCoder*)aRmc connection]; + NSAssert(encoder_connection, NSInternalInconsistencyException); + if (![encoder_connection isValid]) + [NSException raise: NSGenericException format: @"Trying to encode to an invalid Connection.\n" @"You should request NSConnectionDidDieNotification's and\n" @"release all references to the proxy's of invalid Connections."]; - proxy_target = (unsigned int)_object; + proxy_target = _handle; - if (encoder_connection == _connection) { - if (_isLocal) { - /* - * This proxy is a local to us, remote to other side. - */ - proxy_tag = PROXY_LOCAL_FOR_SENDER; + if (encoder_connection == _connection) + { + if (_object) + { + /* + * This proxy is a local to us, remote to other side. + */ + proxy_tag = PROXY_LOCAL_FOR_SENDER; - if (debug_proxy) - NSLog(@"Sending a proxy, will be remote 0x%x connection 0x%x\n", - (unsigned)_object, + if (debug_proxy) + NSLog(@"Sending a proxy, will be remote 0x%x connection 0x%x\n", + (unsigned)proxy_target, (unsigned)_connection); - [aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) - at: &proxy_tag - withName: @"Proxy is local for sender"]; + [aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) + at: &proxy_tag + withName: @"Proxy is local for sender"]; - [aRmc encodeValueOfCType: @encode(typeof(proxy_target)) - at: &proxy_target - withName: @"Proxy target"]; + [aRmc encodeValueOfCType: @encode(typeof(proxy_target)) + at: &proxy_target + withName: @"Proxy target"]; } - else { - /* - * This proxy is a local object on the other side. - */ - proxy_tag = PROXY_LOCAL_FOR_RECEIVER; + else + { + /* + * This proxy is a local object on the other side. + */ + proxy_tag = PROXY_LOCAL_FOR_RECEIVER; - if (debug_proxy) - NSLog(@"Sending a proxy, will be local 0x%x connection 0x%x\n", - (unsigned)_object, + if (debug_proxy) + NSLog(@"Sending a proxy, will be local 0x%x connection 0x%x\n", + (unsigned)proxy_target, (unsigned)_connection); - [aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) - at: &proxy_tag - withName: @"Proxy is local for receiver"]; + [aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) + at: &proxy_tag + withName: @"Proxy is local for receiver"]; - [aRmc encodeValueOfCType: @encode(typeof(proxy_target)) - at: &proxy_target - withName: @"Proxy target"]; + [aRmc encodeValueOfCType: @encode(typeof(proxy_target)) + at: &proxy_target + withName: @"Proxy target"]; } } - else { - /* - * This proxy will still be remote on the other side - */ - NSPort *proxy_connection_out_port = [_connection sendPort]; + else + { + /* + * This proxy will still be remote on the other side + */ + NSPort *proxy_connection_out_port = [_connection sendPort]; - NSAssert(proxy_connection_out_port, NSInternalInconsistencyException); - NSAssert([proxy_connection_out_port isValid], NSInternalInconsistencyException); - NSAssert(proxy_connection_out_port != [encoder_connection sendPort], NSInternalInconsistencyException); + NSAssert(proxy_connection_out_port, NSInternalInconsistencyException); + NSAssert([proxy_connection_out_port isValid], 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) - NSLog(@"Sending triangle-connection proxy 0x%x " - @"proxy-conn 0x%x to-conn 0x%x\n", + if (debug_proxy) + NSLog(@"Sending triangle-connection proxy 0x%x " + @"proxy-conn 0x%x to-conn 0x%x\n", (unsigned)_object, (unsigned)_connection, (unsigned)encoder_connection); - /* - * It's remote here, so we need to tell other side where to form - * triangle connection to - */ - [aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) - at: &proxy_tag - withName: @"Proxy is remote for both sender and receiver"]; + /* + * It's remote here, so we need to tell other side where to form + * triangle connection to + */ + [aRmc encodeValueOfCType: @encode(typeof(proxy_tag)) + at: &proxy_tag + withName: @"Proxy remote for both sender and receiver"]; - [aRmc encodeValueOfCType: @encode(typeof(proxy_target)) - at: &proxy_target - withName: @"Proxy target"]; + [aRmc encodeValueOfCType: @encode(typeof(proxy_target)) + at: &proxy_target + withName: @"Proxy target"]; - [aRmc encodeBycopyObject: proxy_connection_out_port - withName: @"Proxy outPort"]; - /* - * Make a note that we have passed this on to another process. - */ - _isVended = YES; + [aRmc encodeBycopyObject: proxy_connection_out_port + withName: @"Proxy outPort"]; + /* + * Make a note that we have passed this on to another process. + */ + _isVended = YES; } } @@ -215,203 +229,212 @@ format: @"NSDistantObject objects only encode with PortEncoder class"]; */ - (void) forwardInvocation: (NSInvocation*)anInvocation { - [NSException raise: NSInvalidArgumentException - format: @"Not yet implemented '%s'", - sel_get_name(_cmd)]; + [NSException raise: NSInvalidArgumentException + format: @"Not yet implemented '%s'", sel_get_name(_cmd)]; } -- initWithCoder: coder +- (id) initWithCoder: (NSCoder*)coder { - [NSException raise: NSInvalidArgumentException - format: @"Not yet implemented '%s'", - sel_get_name(_cmd)]; - return nil; + [NSException raise: NSInvalidArgumentException + format: @"Not yet implemented '%s'", sel_get_name(_cmd)]; + 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 - * combination, don't create a new one, just return the old one. - */ - if ((new_proxy = [aConnection localForTarget: anObject])) { - [self dealloc]; - return [new_proxy retain]; + /* + * If there already is a local proxy for this target/connection + * combination, don't create a new one, just return the old one. + */ + if ((new_proxy = [aConnection localForObject: anObject])) + { + [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 - * application wants to use it. - */ - _object = [anObject retain]; + /* + * We retain our target object so it can't disappear while a remote + * application wants to use it. + */ + _object = [anObject retain]; - /* - * We register this object with the connection using it. - */ - [_connection addLocalObject: self]; + [handle_lock lock]; + _handle = ++handle_counter; + [handle_lock unlock]; - 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); - 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, - * don't create a new one, just return the old one. - */ - if ((new_proxy = [aConnection proxyForTarget: anObject])) { - [self dealloc]; - return [new_proxy retain]; + /* + * If there already is a proxy for this target/connection combination, + * don't create a new one, just return the old one. + */ + if ((new_proxy = [aConnection proxyForTarget: target])) + { + [self dealloc]; + return [new_proxy retain]; } - _isLocal = NO; - _object = anObject; + _object = nil; + _handle = target; - /* - * We retain our connection so it can't disappear while the app - * may want to use it. - */ - _connection = [aConnection retain]; + /* + * We retain our connection so it can't disappear while the app + * may want to use it. + */ + _connection = [aConnection retain]; - /* - * We register this object with the connection using it. - */ - [_connection addProxy: self]; + /* + * We register this object with the connection using it. + */ + [_connection addProxy: self]; - if (debug_proxy) - NSLog(@"Created new proxy=0x%x object 0x%x connection 0x%x\n", - (unsigned)self, (unsigned)_object, (unsigned)_connection); + if (debug_proxy) + NSLog(@"Created new proxy=0x%x object 0x%x connection 0x%x\n", + (unsigned)self, (unsigned)_object, (unsigned)_connection); - return self; + return self; } - (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector { - if (_isLocal) { - return [_object methodSignatureForSelector: aSelector]; + if (_object) + { + return [_object methodSignatureForSelector: aSelector]; } - else { - if (_protocol) { - const char *types = 0; + else + { + if (_protocol) + { + const char *types = 0; - struct objc_method_description* mth; + struct objc_method_description* mth; - mth = [_protocol descriptionForInstanceMethod: aSelector]; - if (mth == 0) { - mth = [_protocol descriptionForClassMethod: aSelector]; + mth = [_protocol descriptionForInstanceMethod: aSelector]; + if (mth == 0) + { + mth = [_protocol descriptionForClassMethod: aSelector]; } - if (mth != 0) { - types = mth->types; + if (mth != 0) + { + types = mth->types; } - if (types == 0) { - return nil; + if (types == 0) + { + return nil; } - return [NSMethodSignature signatureWithObjCTypes: types]; + return [NSMethodSignature signatureWithObjCTypes: types]; } - else { - arglist_t args; + else + { + arglist_t args; - /* - * No protocol - so try forwarding the message. - */ - args = __builtin_apply_args(); - __builtin_return([self forward: _cmd : args]); + /* + * No protocol - so try forwarding the message. + */ + args = __builtin_apply_args(); + __builtin_return([self forward: _cmd : args]); } } } - (void) setProtocolForProxy: (Protocol*)aProtocol { - _protocol = aProtocol; + _protocol = aProtocol; } - (void) release { - if ([self retainCount] == 2) { - if (_isLocal == NO) { - /* - * 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 - * that we don't have problems when the connection releases us. - */ - [super retain]; - [_connection removeProxy:self]; - [super release]; + if ([self retainCount] == 2) + { + 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 + * that we don't have problems when the connection releases us. + */ + [super retain]; + [_connection removeProxy: self]; + [super release]; } } - [super release]; + [super release]; } @end @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 { - return self; + return self; } 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)) - if (class==aClassObject) - return YES; - return NO; + for (class = self; class!=Nil; class = class_get_super_class(class)) + if (class==aClassObject) + return YES; + return NO; } + newWithCoder: aRmc { - unsigned char proxy_tag; - unsigned target; - id decoder_connection; + gsu8 proxy_tag; + gsu32 target; + id decoder_connection; - if ([aRmc class] != [PortDecoder class]) - [NSException raise: NSGenericException + if ([aRmc class] != [PortDecoder class]) + [NSException raise: NSGenericException format: @"NSDistantObject objects only decode with PortDecoder class"]; - decoder_connection = [aRmc connection]; - NSAssert(decoder_connection, NSInternalInconsistencyException); + decoder_connection = [aRmc connection]; + NSAssert(decoder_connection, NSInternalInconsistencyException); - /* First get the tag, so we know what values need to be decoded. */ - [aRmc decodeValueOfCType: @encode(typeof(proxy_tag)) - at: &proxy_tag - withName: NULL]; + /* First get the tag, so we know what values need to be decoded. */ + [aRmc decodeValueOfCType: @encode(typeof(proxy_tag)) + at: &proxy_tag + withName: NULL]; - switch (proxy_tag) { - - case PROXY_LOCAL_FOR_RECEIVER: + 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 address 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. + * Lookup the target handle to ensure that it exists here. * Return a retained copy of the local target object. */ [aRmc decodeValueOfCType: @encode(typeof(target)) @@ -419,24 +442,27 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; withName: NULL]; 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); - if (![[decoder_connection class] includesLocalObject: (id)target]) - [NSException raise: @"ProxyDecodedBadTarget" - format: @"No local object with given address"]; + if (![[decoder_connection class] includesLocalTarget: target]) + [NSException raise: @"ProxyDecodedBadTarget" + format: @"No local object with given address"]; + else + { + NSDistantObject *o; - { - id local = [NSDistantObject proxyWithLocal: (id)target - connection: decoder_connection]; + o = [decoder_connection includesLocalTarget: target]; + if (debug_proxy) + { + NSLog(@"Local object is 0x%x (0x%x)\n", + (unsigned)o, (unsigned)[o localForProxy]); + } + [self release]; + return [[o localForProxy] retain]; + } - if (debug_proxy) - NSLog(@"Local object is 0x%x (0x%x)\n", - (unsigned)local, (unsigned)[local targetForProxy]); - return [[local targetForProxy] retain]; - } - - case PROXY_LOCAL_FOR_SENDER: + 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 @@ -444,16 +470,16 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; * return the proxy object we already created for this target, or * create a new proxy object if necessary. */ - [aRmc decodeValueOfCType: @encode(typeof(target)) - at: &target - withName: NULL]; - if (debug_proxy) - NSLog(@"Receiving a proxy, was local 0x%x connection 0x%x\n", - (unsigned)target, (unsigned)decoder_connection); - return [[NSDistantObject proxyWithTarget: (id)target - connection: decoder_connection] retain]; + [aRmc decodeValueOfCType: @encode(typeof(target)) + at: &target + withName: NULL]; + if (debug_proxy) + NSLog(@"Receiving a proxy, was local 0x%x connection 0x%x\n", + (unsigned)target, (unsigned)decoder_connection); + return [[NSDistantObject proxyWithTarget: target + 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 * 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 * local object for our use. */ - if ([proxy_connection includesProxyForTarget: (id)target] == NO) - [proxy_connection retainTarget: target]; + if ([proxy_connection includesProxyForTarget: target] == NO) + [proxy_connection retainTarget: target]; - result = [[NSDistantObject proxyWithTarget: (id)target + result = [[NSDistantObject proxyWithTarget: target connection: proxy_connection] retain]; return result; } @@ -555,41 +581,46 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; #endif } -- targetForProxy +- (id) localForProxy { - return _object; + return _object; +} + +- (gsu32) targetForProxy +{ + return _handle; } - forward: (SEL)aSel :(arglist_t)frame { - if (debug_proxy) - NSLog(@"NSDistantObject forwarding %s\n", sel_get_name(aSel)); + if (debug_proxy) + NSLog(@"NSDistantObject forwarding %s\n", sel_get_name(aSel)); - if (![_connection isValid]) - [NSException + if (![_connection isValid]) + [NSException raise: NSGenericException format: @"Trying to send message to an invalid Proxy.\n" @"You should request NSConnectionDidDieNotification's and\n" @"release all references to the proxy's of invalid Connections."]; - return [_connection forwardForProxy: self - selector: aSel - argFrame: frame]; + return [_connection forwardForProxy: self + selector: aSel + argFrame: frame]; } - classForCoder { - return object_get_class (self); + return object_get_class (self); } - classForPortCoder { - return object_get_class (self); + return object_get_class (self); } - replacementObjectForCoder:(NSCoder*)aCoder { - return self; + return self; } - replacementObjectForPortCoder:(NSPortCoder*)aCoder @@ -621,16 +652,16 @@ format: @"NSDistantObject objects only decode with PortDecoder class"]; - (Class) classForPortCoder { - return [self class]; + return [self class]; } - replacementObjectForPortCoder: (NSPortCoder*)aRmc; { - if ([aRmc isBycopy]) - return self; - else - return [NSDistantObject proxyWithLocal: self - connection: [aRmc connection]]; + if ([aRmc isBycopy]) + return self; + else + return [NSDistantObject proxyWithLocal: self + connection: [aRmc connection]]; } @end