mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +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
e12e65212d
commit
a85fdf039c
4 changed files with 95 additions and 85 deletions
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
* Source/NSArray.m: ([removeObjectsFromIndices:numIndices:])
|
* Source/NSArray.m: ([removeObjectsFromIndices:numIndices:])
|
||||||
bugfix for sorting by Kelvin Sherlock.
|
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>
|
2002-12-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,9 @@ enum {
|
||||||
* by NSDistantObject et al for implementation of Distributed objects.
|
* by NSDistantObject et al for implementation of Distributed objects.
|
||||||
*/
|
*/
|
||||||
@interface NSConnection (Internal)
|
@interface NSConnection (Internal)
|
||||||
+ (NSDistantObject*) includesLocalTarget: (unsigned)target;
|
|
||||||
- (NSDistantObject*) includesLocalTarget: (unsigned)target;
|
- (NSDistantObject*) includesLocalTarget: (unsigned)target;
|
||||||
- (NSDistantObject*) localForObject: (id)object;
|
- (NSDistantObject*) localForObject: (id)object;
|
||||||
|
- (NSDistantObject*) locateLocalTarget: (unsigned)target;
|
||||||
- (NSDistantObject*) proxyForTarget: (unsigned)target;
|
- (NSDistantObject*) proxyForTarget: (unsigned)target;
|
||||||
- (void) retainTarget: (unsigned)target;
|
- (void) retainTarget: (unsigned)target;
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -1874,7 +1874,8 @@ static void retEncoder (DOContext *ctxt)
|
||||||
|
|
||||||
[self _sendOutRmc: ctxt.encoder type: METHOD_REQUEST];
|
[self _sendOutRmc: ctxt.encoder type: METHOD_REQUEST];
|
||||||
ctxt.encoder = nil;
|
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)
|
if (needsResponse == NO)
|
||||||
{
|
{
|
||||||
|
@ -2540,46 +2541,15 @@ static void callEncoder (DOContext *ctxt)
|
||||||
|
|
||||||
if ([self includesLocalTarget: target] == nil)
|
if ([self includesLocalTarget: target] == nil)
|
||||||
{
|
{
|
||||||
GSLocalCounter *counter;
|
NSDistantObject *proxy = [self locateLocalTarget: target];
|
||||||
|
|
||||||
M_LOCK(global_proxies_gate);
|
if (proxy == nil)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
[op encodeObject: @"target not found anywhere"];
|
[op encodeObject: @"target not found anywhere"];
|
||||||
if (debug_connection > 3)
|
|
||||||
NSLog(@"target (0x%x) not found anywhere for retain", target);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[distantObjectClass proxyWithLocal: counter->object
|
[op encodeObject: nil]; // success
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2619,9 +2589,9 @@ static void callEncoder (DOContext *ctxt)
|
||||||
unsigned target;
|
unsigned target;
|
||||||
NSDistantObject *p;
|
NSDistantObject *p;
|
||||||
int sequence;
|
int sequence;
|
||||||
id o;
|
id o;
|
||||||
SEL sel;
|
SEL sel;
|
||||||
const char *type;
|
const char *type;
|
||||||
struct objc_method* m;
|
struct objc_method* m;
|
||||||
|
|
||||||
NSParameterAssert(_receivePort);
|
NSParameterAssert(_receivePort);
|
||||||
|
@ -3155,30 +3125,27 @@ static void callEncoder (DOContext *ctxt)
|
||||||
counter->ref--;
|
counter->ref--;
|
||||||
if ((val = counter->ref) == 0)
|
if ((val = counter->ref) == 0)
|
||||||
{
|
{
|
||||||
|
id item;
|
||||||
/*
|
/*
|
||||||
* If this proxy has been vended onwards by another process, we
|
* If this proxy has been vended onwards by another process, we
|
||||||
* need to keep a reference to the local object around for a
|
* need to keep a reference to the local object around for a
|
||||||
* while in case that other process needs it.
|
* while in case that other process needs it.
|
||||||
*/
|
*/
|
||||||
if (0)
|
if (timer == nil)
|
||||||
{
|
{
|
||||||
id item;
|
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
|
||||||
|
target: connectionClass
|
||||||
if (timer == nil)
|
selector: @selector(_timeout:)
|
||||||
{
|
userInfo: nil
|
||||||
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
|
repeats: YES];
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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(objectToCounter, (void*)anObj);
|
||||||
NSMapRemove(targetToCounter, (void*)target);
|
NSMapRemove(targetToCounter, (void*)target);
|
||||||
}
|
}
|
||||||
|
@ -3242,6 +3209,63 @@ static void callEncoder (DOContext *ctxt)
|
||||||
NS_ENDHANDLER
|
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
|
- (void) retainTarget: (unsigned)target
|
||||||
{
|
{
|
||||||
NS_DURING
|
NS_DURING
|
||||||
|
@ -3266,6 +3290,8 @@ static void callEncoder (DOContext *ctxt)
|
||||||
[self _doneInRmc: ip];
|
[self _doneInRmc: ip];
|
||||||
if (result != nil)
|
if (result != nil)
|
||||||
NSLog(@"failed to retain target - %@", result);
|
NSLog(@"failed to retain target - %@", result);
|
||||||
|
else if (debug_connection > 3)
|
||||||
|
NSLog(@"sending retain for target - %u", target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_HANDLER
|
NS_HANDLER
|
||||||
|
@ -3379,7 +3405,7 @@ static void callEncoder (DOContext *ctxt)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) includesLocalTarget: (unsigned)target
|
- (NSDistantObject*) includesLocalTarget: (unsigned)target
|
||||||
{
|
{
|
||||||
NSDistantObject *ret;
|
NSDistantObject *ret;
|
||||||
GSIMapNode node;
|
GSIMapNode node;
|
||||||
|
@ -3399,23 +3425,6 @@ static void callEncoder (DOContext *ctxt)
|
||||||
return ret;
|
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 */
|
/* Accessing ivars */
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ enum
|
||||||
gsu8 proxy_tag;
|
gsu8 proxy_tag;
|
||||||
unsigned target;
|
unsigned target;
|
||||||
id decoder_connection;
|
id decoder_connection;
|
||||||
|
NSDistantObject *o;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
|
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
|
||||||
|
@ -155,7 +156,8 @@ enum
|
||||||
NSLog(@"Receiving a proxy for local object 0x%x "
|
NSLog(@"Receiving a proxy for local object 0x%x "
|
||||||
@"connection 0x%x\n", target, (gsaddr)decoder_connection);
|
@"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"
|
[NSException raise: @"ProxyDecodedBadTarget"
|
||||||
format: @"No local object with given target (0x%x)",
|
format: @"No local object with given target (0x%x)",
|
||||||
|
@ -163,9 +165,6 @@ enum
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSDistantObject *o;
|
|
||||||
|
|
||||||
o = [decoder_connection includesLocalTarget: target];
|
|
||||||
if (debug_proxy)
|
if (debug_proxy)
|
||||||
{
|
{
|
||||||
NSLog(@"Local object is 0x%x (0x%x)\n",
|
NSLog(@"Local object is 0x%x (0x%x)\n",
|
||||||
|
@ -511,9 +510,10 @@ enum
|
||||||
|
|
||||||
- (id) initWithCoder: (NSCoder*)aCoder
|
- (id) initWithCoder: (NSCoder*)aCoder
|
||||||
{
|
{
|
||||||
gsu8 proxy_tag;
|
gsu8 proxy_tag;
|
||||||
unsigned target;
|
unsigned target;
|
||||||
id decoder_connection;
|
id decoder_connection;
|
||||||
|
NSDistantObject *o;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
|
if ([aCoder isKindOfClass: [NSPortCoder class]] == NO)
|
||||||
|
@ -548,7 +548,8 @@ enum
|
||||||
NSLog(@"Receiving a proxy for local object 0x%x "
|
NSLog(@"Receiving a proxy for local object 0x%x "
|
||||||
@"connection 0x%x\n", target, (gsaddr)decoder_connection);
|
@"connection 0x%x\n", target, (gsaddr)decoder_connection);
|
||||||
|
|
||||||
if (![[decoder_connection class] includesLocalTarget: target])
|
o = [decoder_connection locateLocalTarget: target];
|
||||||
|
if (o == nil)
|
||||||
{
|
{
|
||||||
RELEASE(self);
|
RELEASE(self);
|
||||||
[NSException raise: @"ProxyDecodedBadTarget"
|
[NSException raise: @"ProxyDecodedBadTarget"
|
||||||
|
@ -557,9 +558,6 @@ enum
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSDistantObject *o;
|
|
||||||
|
|
||||||
o = [decoder_connection includesLocalTarget: target];
|
|
||||||
if (debug_proxy)
|
if (debug_proxy)
|
||||||
{
|
{
|
||||||
NSLog(@"Local object is 0x%x (0x%x)\n",
|
NSLog(@"Local object is 0x%x (0x%x)\n",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue