mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-01 01:01:03 +00:00
Restructure handling of thread exit to avoid setting up separate
notification handlers for each connection. Optimise a little. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20380 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
aa686b1411
commit
d3bbcd8394
2 changed files with 48 additions and 27 deletions
|
@ -1,6 +1,11 @@
|
||||||
2004-11-25 Richard Frith-Macdonald <rfm@gnu.org>
|
2004-11-25 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Tools/gdomap.c: make respond to --help as to -H
|
* Tools/gdomap.c: make respond to --help as to -H
|
||||||
|
* Source/NSConnection.m: ([_threadWillExit:]) change to be a class
|
||||||
|
method rather then instance method. Implement removeal of runloop
|
||||||
|
of exiting thread unconditionally from all threads...
|
||||||
|
the code in [removeRunLoop:] is safely lock protected.
|
||||||
|
Use GSRunLoopForThread() for performance throughout.
|
||||||
|
|
||||||
2004-11-24 15:08 Patrick McFarland <unknown@panax.com>
|
2004-11-24 15:08 Patrick McFarland <unknown@panax.com>
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@
|
||||||
#include "Foundation/NSDebug.h"
|
#include "Foundation/NSDebug.h"
|
||||||
#include "GSInvocation.h"
|
#include "GSInvocation.h"
|
||||||
|
|
||||||
|
extern NSRunLoop *GSRunLoopForThread(NSThread*);
|
||||||
|
|
||||||
#define F_LOCK(X) {NSDebugFLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
#define F_LOCK(X) {NSDebugFLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
||||||
#define F_UNLOCK(X) {NSDebugFLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
|
#define F_UNLOCK(X) {NSDebugFLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
|
||||||
#define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
#define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
||||||
|
@ -211,7 +213,7 @@ stringFromMsgType(int type)
|
||||||
- (void) _service_rootObject: (NSPortCoder*)rmc;
|
- (void) _service_rootObject: (NSPortCoder*)rmc;
|
||||||
- (void) _service_shutdown: (NSPortCoder*)rmc;
|
- (void) _service_shutdown: (NSPortCoder*)rmc;
|
||||||
- (void) _service_typeForSelector: (NSPortCoder*)rmc;
|
- (void) _service_typeForSelector: (NSPortCoder*)rmc;
|
||||||
- (void) _threadWillExit: (NSNotification*)notification;
|
+ (void) _threadWillExit: (NSNotification*)notification;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#define _proxiesGate _refGate
|
#define _proxiesGate _refGate
|
||||||
|
@ -488,6 +490,8 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
{
|
{
|
||||||
if (self == [NSConnection class])
|
if (self == [NSConnection class])
|
||||||
{
|
{
|
||||||
|
NSNotificationCenter *nc;
|
||||||
|
|
||||||
connectionClass = self;
|
connectionClass = self;
|
||||||
dateClass = [NSDate class];
|
dateClass = [NSDate class];
|
||||||
distantObjectClass = [NSDistantObject class];
|
distantObjectClass = [NSDistantObject class];
|
||||||
|
@ -520,6 +524,16 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
{
|
{
|
||||||
root_object_map_gate = [GSLazyLock new];
|
root_object_map_gate = [GSLazyLock new];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When any thread exits, we must check to see if we are using its
|
||||||
|
* runloop, and remove ourselves from it if necessary.
|
||||||
|
*/
|
||||||
|
nc = [NSNotificationCenter defaultCenter];
|
||||||
|
[nc addObserver: self
|
||||||
|
selector: @selector(_threadWillExit:)
|
||||||
|
name: NSThreadWillExitNotification
|
||||||
|
object: nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +653,7 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
{
|
{
|
||||||
if ([_runLoops indexOfObjectIdenticalTo: loop] == NSNotFound)
|
if ([_runLoops indexOfObjectIdenticalTo: loop] == NSNotFound)
|
||||||
{
|
{
|
||||||
unsigned c = [_requestModes count];
|
unsigned c = [_requestModes count];
|
||||||
|
|
||||||
while (c-- > 0)
|
while (c-- > 0)
|
||||||
{
|
{
|
||||||
|
@ -892,7 +906,7 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
* Set up request modes array and make sure the receiving port
|
* Set up request modes array and make sure the receiving port
|
||||||
* is added to the run loop to get data.
|
* is added to the run loop to get data.
|
||||||
*/
|
*/
|
||||||
loop = [runLoopClass currentRunLoop];
|
loop = GSRunLoopForThread(nil);
|
||||||
_runLoops = [[NSMutableArray alloc] initWithObjects: &loop count: 1];
|
_runLoops = [[NSMutableArray alloc] initWithObjects: &loop count: 1];
|
||||||
_requestModes = [[NSMutableArray alloc] initWithCapacity: 2];
|
_requestModes = [[NSMutableArray alloc] initWithCapacity: 2];
|
||||||
[self addRequestMode: NSDefaultRunLoopMode];
|
[self addRequestMode: NSDefaultRunLoopMode];
|
||||||
|
@ -953,15 +967,6 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
object: s];
|
object: s];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* When any thread exits, we must check to see if we are using its
|
|
||||||
* runloop, and remove ourselves from it if necessary.
|
|
||||||
*/
|
|
||||||
[nCenter addObserver: self
|
|
||||||
selector: @selector(_threadWillExit:)
|
|
||||||
name: NSThreadWillExitNotification
|
|
||||||
object: nil];
|
|
||||||
|
|
||||||
/* In order that connections may be deallocated - there is an
|
/* In order that connections may be deallocated - there is an
|
||||||
implementation of [-release] to automatically remove the connection
|
implementation of [-release] to automatically remove the connection
|
||||||
from this array when it is the only thing retaining it. */
|
from this array when it is the only thing retaining it. */
|
||||||
|
@ -969,7 +974,7 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
M_UNLOCK(connection_table_gate);
|
M_UNLOCK(connection_table_gate);
|
||||||
|
|
||||||
[nCenter postNotificationName: NSConnectionDidInitializeNotification
|
[nCenter postNotificationName: NSConnectionDidInitializeNotification
|
||||||
object: self];
|
object: self];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -1092,7 +1097,6 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
}
|
}
|
||||||
M_UNLOCK(_proxiesGate);
|
M_UNLOCK(_proxiesGate);
|
||||||
|
|
||||||
#if 1
|
|
||||||
/*
|
/*
|
||||||
* If we are invalidated, we shouldn't be receiving any event and
|
* If we are invalidated, we shouldn't be receiving any event and
|
||||||
* should not need to be in any run loops.
|
* should not need to be in any run loops.
|
||||||
|
@ -1101,7 +1105,6 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
{
|
{
|
||||||
[self removeRunLoop: [_runLoops lastObject]];
|
[self removeRunLoop: [_runLoops lastObject]];
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalidate the current conversation so we don't leak.
|
* Invalidate the current conversation so we don't leak.
|
||||||
|
@ -1400,7 +1403,7 @@ static NSLock *cached_proxies_gate = nil;
|
||||||
*/
|
*/
|
||||||
- (void) runInNewThread
|
- (void) runInNewThread
|
||||||
{
|
{
|
||||||
[self removeRunLoop: [runLoopClass currentRunLoop]];
|
[self removeRunLoop: GSRunLoopForThread(nil)];
|
||||||
[NSThread detachNewThreadSelector: @selector(_runInNewThread)
|
[NSThread detachNewThreadSelector: @selector(_runInNewThread)
|
||||||
toTarget: self
|
toTarget: self
|
||||||
withObject: nil];
|
withObject: nil];
|
||||||
|
@ -1750,7 +1753,8 @@ static void retEncoder (DOContext *ctxt)
|
||||||
const char *type;
|
const char *type;
|
||||||
retval_t retframe;
|
retval_t retframe;
|
||||||
DOContext ctxt;
|
DOContext ctxt;
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
NSThread *thread = GSCurrentThread();
|
||||||
|
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||||
|
|
||||||
memset(&ctxt, 0, sizeof(ctxt));
|
memset(&ctxt, 0, sizeof(ctxt));
|
||||||
ctxt.connection = self;
|
ctxt.connection = self;
|
||||||
|
@ -1893,7 +1897,8 @@ static void retEncoder (DOContext *ctxt)
|
||||||
BOOL needsResponse;
|
BOOL needsResponse;
|
||||||
const char *type;
|
const char *type;
|
||||||
DOContext ctxt;
|
DOContext ctxt;
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
NSThread *thread = GSCurrentThread();
|
||||||
|
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||||
|
|
||||||
if ([_runLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound)
|
if ([_runLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound)
|
||||||
{
|
{
|
||||||
|
@ -2238,7 +2243,7 @@ static void retEncoder (DOContext *ctxt)
|
||||||
|
|
||||||
- (void) _runInNewThread
|
- (void) _runInNewThread
|
||||||
{
|
{
|
||||||
NSRunLoop *loop = [runLoopClass currentRunLoop];
|
NSRunLoop *loop = GSRunLoopForThread(nil);
|
||||||
|
|
||||||
[self addRunLoop: loop];
|
[self addRunLoop: loop];
|
||||||
[loop run];
|
[loop run];
|
||||||
|
@ -2356,7 +2361,8 @@ static void callEncoder (DOContext *ctxt)
|
||||||
*/
|
*/
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
NSThread *thread = GSCurrentThread();
|
||||||
|
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||||
|
|
||||||
NSParameterAssert (_isValid);
|
NSParameterAssert (_isValid);
|
||||||
if ([_runLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound)
|
if ([_runLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound)
|
||||||
|
@ -2619,7 +2625,8 @@ static void callEncoder (DOContext *ctxt)
|
||||||
NSTimeInterval last_interval = 0.0001;
|
NSTimeInterval last_interval = 0.0001;
|
||||||
NSTimeInterval delay_interval = last_interval;
|
NSTimeInterval delay_interval = last_interval;
|
||||||
NSDate *delay_date = nil;
|
NSDate *delay_date = nil;
|
||||||
NSRunLoop *runLoop = [runLoopClass currentRunLoop];
|
NSThread *thread = GSCurrentThread();
|
||||||
|
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||||
BOOL isLocked = NO;
|
BOOL isLocked = NO;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3535,17 +3542,26 @@ static void callEncoder (DOContext *ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On thread exit, we need to be removed from the runloop of the thread
|
* On thread exit, we need all connections to be removed from the runloop
|
||||||
* or we will retain that and cause a memory leak.
|
* of the thread or they will retain that and cause a memory leak.
|
||||||
*/
|
*/
|
||||||
- (void) _threadWillExit: (NSNotification*)notification
|
+ (void) _threadWillExit: (NSNotification*)notification
|
||||||
{
|
{
|
||||||
extern NSRunLoop *GSRunLoopForThread(NSThread*);
|
|
||||||
NSRunLoop *runLoop = GSRunLoopForThread([notification object]);
|
NSRunLoop *runLoop = GSRunLoopForThread([notification object]);
|
||||||
|
|
||||||
if ([_runLoops indexOfObjectIdenticalTo: runLoop] != NSNotFound)
|
if (runLoop != nil)
|
||||||
{
|
{
|
||||||
[self removeRunLoop: runLoop];
|
NSHashEnumerator enumerator;
|
||||||
|
NSConnection *c;
|
||||||
|
|
||||||
|
M_LOCK(connection_table_gate);
|
||||||
|
enumerator = NSEnumerateHashTable(connection_table);
|
||||||
|
while ((c = (NSConnection*)NSNextHashEnumeratorItem(&enumerator)) != nil)
|
||||||
|
{
|
||||||
|
[c removeRunLoop: runLoop];
|
||||||
|
}
|
||||||
|
NSEndHashTableEnumeration(&enumerator);
|
||||||
|
M_UNLOCK(connection_table_gate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue