mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +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
aee109b5ee
commit
2c65d630c4
2 changed files with 48 additions and 27 deletions
|
@ -1,6 +1,11 @@
|
|||
2004-11-25 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* 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>
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@
|
|||
#include "Foundation/NSDebug.h"
|
||||
#include "GSInvocation.h"
|
||||
|
||||
extern NSRunLoop *GSRunLoopForThread(NSThread*);
|
||||
|
||||
#define F_LOCK(X) {NSDebugFLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
||||
#define F_UNLOCK(X) {NSDebugFLLog(@"GSConnection",@"Unlock %@",X);[X unlock];}
|
||||
#define M_LOCK(X) {NSDebugMLLog(@"GSConnection",@"Lock %@",X);[X lock];}
|
||||
|
@ -211,7 +213,7 @@ stringFromMsgType(int type)
|
|||
- (void) _service_rootObject: (NSPortCoder*)rmc;
|
||||
- (void) _service_shutdown: (NSPortCoder*)rmc;
|
||||
- (void) _service_typeForSelector: (NSPortCoder*)rmc;
|
||||
- (void) _threadWillExit: (NSNotification*)notification;
|
||||
+ (void) _threadWillExit: (NSNotification*)notification;
|
||||
@end
|
||||
|
||||
#define _proxiesGate _refGate
|
||||
|
@ -488,6 +490,8 @@ static NSLock *cached_proxies_gate = nil;
|
|||
{
|
||||
if (self == [NSConnection class])
|
||||
{
|
||||
NSNotificationCenter *nc;
|
||||
|
||||
connectionClass = self;
|
||||
dateClass = [NSDate class];
|
||||
distantObjectClass = [NSDistantObject class];
|
||||
|
@ -520,6 +524,16 @@ static NSLock *cached_proxies_gate = nil;
|
|||
{
|
||||
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)
|
||||
{
|
||||
unsigned c = [_requestModes count];
|
||||
unsigned c = [_requestModes count];
|
||||
|
||||
while (c-- > 0)
|
||||
{
|
||||
|
@ -892,7 +906,7 @@ static NSLock *cached_proxies_gate = nil;
|
|||
* Set up request modes array and make sure the receiving port
|
||||
* is added to the run loop to get data.
|
||||
*/
|
||||
loop = [runLoopClass currentRunLoop];
|
||||
loop = GSRunLoopForThread(nil);
|
||||
_runLoops = [[NSMutableArray alloc] initWithObjects: &loop count: 1];
|
||||
_requestModes = [[NSMutableArray alloc] initWithCapacity: 2];
|
||||
[self addRequestMode: NSDefaultRunLoopMode];
|
||||
|
@ -953,15 +967,6 @@ static NSLock *cached_proxies_gate = nil;
|
|||
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
|
||||
implementation of [-release] to automatically remove the connection
|
||||
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);
|
||||
|
||||
[nCenter postNotificationName: NSConnectionDidInitializeNotification
|
||||
object: self];
|
||||
object: self];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -1092,7 +1097,6 @@ static NSLock *cached_proxies_gate = nil;
|
|||
}
|
||||
M_UNLOCK(_proxiesGate);
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* If we are invalidated, we shouldn't be receiving any event and
|
||||
* should not need to be in any run loops.
|
||||
|
@ -1101,7 +1105,6 @@ static NSLock *cached_proxies_gate = nil;
|
|||
{
|
||||
[self removeRunLoop: [_runLoops lastObject]];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Invalidate the current conversation so we don't leak.
|
||||
|
@ -1400,7 +1403,7 @@ static NSLock *cached_proxies_gate = nil;
|
|||
*/
|
||||
- (void) runInNewThread
|
||||
{
|
||||
[self removeRunLoop: [runLoopClass currentRunLoop]];
|
||||
[self removeRunLoop: GSRunLoopForThread(nil)];
|
||||
[NSThread detachNewThreadSelector: @selector(_runInNewThread)
|
||||
toTarget: self
|
||||
withObject: nil];
|
||||
|
@ -1750,7 +1753,8 @@ static void retEncoder (DOContext *ctxt)
|
|||
const char *type;
|
||||
retval_t retframe;
|
||||
DOContext ctxt;
|
||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||
NSThread *thread = GSCurrentThread();
|
||||
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||
|
||||
memset(&ctxt, 0, sizeof(ctxt));
|
||||
ctxt.connection = self;
|
||||
|
@ -1893,7 +1897,8 @@ static void retEncoder (DOContext *ctxt)
|
|||
BOOL needsResponse;
|
||||
const char *type;
|
||||
DOContext ctxt;
|
||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||
NSThread *thread = GSCurrentThread();
|
||||
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||
|
||||
if ([_runLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound)
|
||||
{
|
||||
|
@ -2238,7 +2243,7 @@ static void retEncoder (DOContext *ctxt)
|
|||
|
||||
- (void) _runInNewThread
|
||||
{
|
||||
NSRunLoop *loop = [runLoopClass currentRunLoop];
|
||||
NSRunLoop *loop = GSRunLoopForThread(nil);
|
||||
|
||||
[self addRunLoop: loop];
|
||||
[loop run];
|
||||
|
@ -2356,7 +2361,8 @@ static void callEncoder (DOContext *ctxt)
|
|||
*/
|
||||
NS_DURING
|
||||
{
|
||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||
NSThread *thread = GSCurrentThread();
|
||||
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||
|
||||
NSParameterAssert (_isValid);
|
||||
if ([_runLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound)
|
||||
|
@ -2619,7 +2625,8 @@ static void callEncoder (DOContext *ctxt)
|
|||
NSTimeInterval last_interval = 0.0001;
|
||||
NSTimeInterval delay_interval = last_interval;
|
||||
NSDate *delay_date = nil;
|
||||
NSRunLoop *runLoop = [runLoopClass currentRunLoop];
|
||||
NSThread *thread = GSCurrentThread();
|
||||
NSRunLoop *runLoop = GSRunLoopForThread(thread);
|
||||
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
|
||||
* or we will retain that and cause a memory leak.
|
||||
* On thread exit, we need all connections to be removed from the runloop
|
||||
* 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]);
|
||||
|
||||
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…
Reference in a new issue