mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
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:
parent
3eb602cc99
commit
b718bd40ad
4 changed files with 95 additions and 85 deletions
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue