Connection retain/release tweaks ... experimental

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@15274 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2002-12-10 11:30:56 +00:00
parent 3eb602cc99
commit b718bd40ad
4 changed files with 95 additions and 85 deletions

View file

@ -2,6 +2,9 @@
* Source/NSArray.m: ([removeObjectsFromIndices:numIndices:])
bugfix for sorting by Kelvin Sherlock.
* Source/NSConnection.m: Experimental code to keep local objects
retained long enough to deal with most cases where the remote
process may want them again.
2002-12-08 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -67,9 +67,9 @@ enum {
* by NSDistantObject et al for implementation of Distributed objects.
*/
@interface NSConnection (Internal)
+ (NSDistantObject*) includesLocalTarget: (unsigned)target;
- (NSDistantObject*) includesLocalTarget: (unsigned)target;
- (NSDistantObject*) localForObject: (id)object;
- (NSDistantObject*) locateLocalTarget: (unsigned)target;
- (NSDistantObject*) proxyForTarget: (unsigned)target;
- (void) retainTarget: (unsigned)target;
@end

View file

@ -1874,7 +1874,8 @@ static void retEncoder (DOContext *ctxt)
[self _sendOutRmc: ctxt.encoder type: METHOD_REQUEST];
ctxt.encoder = nil;
NSDebugMLLog(@"NSConnection", @"Sent message to 0x%x", (gsaddr)self);
NSDebugMLLog(@"NSConnection", @"Sent message (%s) to 0x%x",
sel_get_name(sel), (gsaddr)self);
if (needsResponse == NO)
{
@ -2540,46 +2541,15 @@ static void callEncoder (DOContext *ctxt)
if ([self includesLocalTarget: target] == nil)
{
GSLocalCounter *counter;
NSDistantObject *proxy = [self locateLocalTarget: target];
M_LOCK(global_proxies_gate);
counter = NSMapGet (targetToCounter, (void*)target);
if (counter == nil)
{
/*
* If the target doesn't exist for any connection, but still
* persists in the cache (ie it was recently released) then
* we move it back from the cache to the main maps so we can
* retain it on this connection.
*/
counter = NSMapGet (targetToCached, (void*)target);
if (counter)
{
unsigned t = counter->target;
id o = counter->object;
NSMapInsert(objectToCounter, (void*)o, counter);
NSMapInsert(targetToCounter, (void*)t, counter);
NSMapRemove(targetToCached, (void*)t);
if (debug_connection > 3)
NSLog(@"target (0x%x) moved from cache", target);
}
}
M_UNLOCK(global_proxies_gate);
if (counter == nil)
if (proxy == nil)
{
[op encodeObject: @"target not found anywhere"];
if (debug_connection > 3)
NSLog(@"target (0x%x) not found anywhere for retain", target);
}
else
{
[distantObjectClass proxyWithLocal: counter->object
connection: self];
[op encodeObject: nil];
if (debug_connection > 3)
NSLog(@"retained object (0x%x) target (0x%x) on connection(0x%x)",
counter->object, counter->target, self);
[op encodeObject: nil]; // success
}
}
else
@ -2619,9 +2589,9 @@ static void callEncoder (DOContext *ctxt)
unsigned target;
NSDistantObject *p;
int sequence;
id o;
SEL sel;
const char *type;
id o;
SEL sel;
const char *type;
struct objc_method* m;
NSParameterAssert(_receivePort);
@ -3155,30 +3125,27 @@ static void callEncoder (DOContext *ctxt)
counter->ref--;
if ((val = counter->ref) == 0)
{
id item;
/*
* 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 (0)
if (timer == nil)
{
id item;
if (timer == nil)
{
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
target: connectionClass
selector: @selector(_timeout:)
userInfo: nil
repeats: YES];
}
item = [CachedLocalObject newWithObject: counter time: 30];
NSMapInsert(targetToCached, (void*)target, item);
RELEASE(item);
if (debug_connection > 3)
NSLog(@"placed local object (0x%x) target (0x%x) in cache",
(gsaddr)anObj, target);
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
target: connectionClass
selector: @selector(_timeout:)
userInfo: nil
repeats: YES];
}
item = [CachedLocalObject newWithObject: counter time: 30];
NSMapInsert(targetToCached, (void*)target, item);
RELEASE(item);
if (debug_connection > 3)
NSLog(@"placed local object (0x%x) target (0x%x) in cache",
(gsaddr)anObj, target);
NSMapRemove(objectToCounter, (void*)anObj);
NSMapRemove(targetToCounter, (void*)target);
}
@ -3242,6 +3209,63 @@ static void callEncoder (DOContext *ctxt)
NS_ENDHANDLER
}
- (NSDistantObject*) locateLocalTarget: (unsigned)target
{
NSDistantObject *proxy = nil;
GSIMapNode node;
M_LOCK(global_proxies_gate);
node = GSIMapNodeForKey(_localTargets, (GSIMapKey)target);
if (node != 0)
{
proxy = node->value.obj;
}
else
{
GSLocalCounter *counter;
counter = NSMapGet (targetToCounter, (void*)target);
if (counter == nil)
{
/*
* If the target doesn't exist for any connection, but still
* persists in the cache (ie it was recently released) then
* we move it back from the cache to the main maps so we can
* retain it on this connection.
*/
counter = NSMapGet (targetToCached, (void*)target);
if (counter != nil)
{
unsigned t = counter->target;
id o = counter->object;
NSMapInsert(objectToCounter, (void*)o, counter);
NSMapInsert(targetToCounter, (void*)t, counter);
NSMapRemove(targetToCached, (void*)t);
if (debug_connection > 3)
NSLog(@"target (0x%x) moved from cache", target);
}
}
RETAIN(counter);
M_UNLOCK(global_proxies_gate);
if (counter == nil)
{
if(debug_connection > 3)
NSLog(@"target (0x%x) not found anywhere", target);
}
else
{
proxy = [distantObjectClass proxyWithLocal: counter->object
connection: self];
if (debug_connection > 3)
NSLog(@"retained object (0x%x) target (0x%x) on connection(0x%x)",
counter->object, counter->target, self);
RELEASE(counter);
}
}
return proxy;
}
- (void) retainTarget: (unsigned)target
{
NS_DURING
@ -3266,6 +3290,8 @@ static void callEncoder (DOContext *ctxt)
[self _doneInRmc: ip];
if (result != nil)
NSLog(@"failed to retain target - %@", result);
else if (debug_connection > 3)
NSLog(@"sending retain for target - %u", target);
}
}
NS_HANDLER
@ -3379,7 +3405,7 @@ static void callEncoder (DOContext *ctxt)
return ret;
}
- (id) includesLocalTarget: (unsigned)target
- (NSDistantObject*) includesLocalTarget: (unsigned)target
{
NSDistantObject *ret;
GSIMapNode node;
@ -3399,23 +3425,6 @@ static void callEncoder (DOContext *ctxt)
return ret;
}
/* Check all connections.
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
-includesLocalTarget), because the proxy may have come from a
triangle connection. */
+ (id) includesLocalTarget: (unsigned)target
{
id ret;
/* Don't assert (_isValid); */
M_LOCK(global_proxies_gate);
ret = NSMapGet(targetToCounter, (void*)target);
M_UNLOCK(global_proxies_gate);
return ret;
}
/* Accessing ivars */

View file

@ -122,6 +122,7 @@ enum
gsu8 proxy_tag;
unsigned target;
id decoder_connection;
NSDistantObject *o;
/*
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
@ -155,7 +156,8 @@ enum
NSLog(@"Receiving a proxy for local object 0x%x "
@"connection 0x%x\n", target, (gsaddr)decoder_connection);
if (![[decoder_connection class] includesLocalTarget: target])
o = [decoder_connection locateLocalTarget: target];
if (o == nil)
{
[NSException raise: @"ProxyDecodedBadTarget"
format: @"No local object with given target (0x%x)",
@ -163,9 +165,6 @@ enum
}
else
{
NSDistantObject *o;
o = [decoder_connection includesLocalTarget: target];
if (debug_proxy)
{
NSLog(@"Local object is 0x%x (0x%x)\n",
@ -511,9 +510,10 @@ enum
- (id) initWithCoder: (NSCoder*)aCoder
{
gsu8 proxy_tag;
unsigned target;
id decoder_connection;
gsu8 proxy_tag;
unsigned target;
id decoder_connection;
NSDistantObject *o;
/*
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
@ -548,7 +548,8 @@ enum
NSLog(@"Receiving a proxy for local object 0x%x "
@"connection 0x%x\n", target, (gsaddr)decoder_connection);
if (![[decoder_connection class] includesLocalTarget: target])
o = [decoder_connection locateLocalTarget: target];
if (o == nil)
{
RELEASE(self);
[NSException raise: @"ProxyDecodedBadTarget"
@ -557,9 +558,6 @@ enum
}
else
{
NSDistantObject *o;
o = [decoder_connection includesLocalTarget: target];
if (debug_proxy)
{
NSLog(@"Local object is 0x%x (0x%x)\n",