Thread safety fixup

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@23408 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2006-09-07 11:47:45 +00:00
parent 056a870532
commit a00f8e94c7
3 changed files with 44 additions and 42 deletions

View file

@ -1,7 +1,11 @@
2006-09-10 Richard Frith-Macdonald <rfm@gnu.org>
2006-09-07 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSObject.h: Fix incorrect backward compatibility
setting for openstep version.
* Source/NSObject.m: minor tweak ... put debugging code in the object
reference counting function rather than the release method.
* Source/NSConnection.m: Change release implementation for better
protection of global connection table management.
2006-09-06 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -701,6 +701,7 @@ static NSLock *cached_proxies_gate = nil;
{
if (debug_connection)
NSLog(@"deallocating %@", self);
[self gcFinalize];
[super dealloc];
}
@ -1279,26 +1280,24 @@ static NSLock *cached_proxies_gate = nil;
- (void) release
{
/*
* If this would cause the connection to be deallocated then we
* must perform all necessary work (done in [-gcFinalize]).
*
* We bracket the code with a retain and release so that any
* retain/release pairs in the code won't cause recursion.
*
* We lock the connection table while checking, to prevent
* another thread from grabbing this connection while we are
* finalizing/deallocating it.
/* We lock the connection table while checking, to prevent
* another thread from grabbing this connection while we are
* checking it.
* If we are going to deallocate the object, we first remove
* it from the table so that no other thread will find it
* and try to use it while it is being deallocated.
*/
M_LOCK(connection_table_gate);
if ([self retainCount] == 1)
if (NSDecrementExtraRefCountWasZero(self))
{
[super retain];
[self gcFinalize];
[super release];
NSHashRemove(connection_table, self);
M_UNLOCK(connection_table_gate);
[self dealloc];
}
else
{
M_UNLOCK(connection_table_gate);
}
M_UNLOCK(connection_table_gate);
[super release];
}
/**

View file

@ -65,6 +65,20 @@
extern BOOL __objc_responds_to(id, SEL);
#endif
/* When this is `YES', every call to release/autorelease, checks to
make sure isn't being set up to release itself too many times.
This does not need mutex protection. */
static BOOL double_release_check_enabled = NO;
/* The Class responsible for handling autorelease's. This does not
need mutex protection, since it is simply a pointer that gets read
and set. */
static id autorelease_class = nil;
static SEL autorelease_sel;
static IMP autorelease_imp;
#if GS_WITH_GC
#include <gc.h>
@ -242,12 +256,21 @@ static GSIMapTable_t retain_counts = {0};
* (and hence whether the extra reference count was decremented).<br />
* This function is used by the [NSObject-release] method.
*/
inline BOOL
BOOL
NSDecrementExtraRefCountWasZero(id anObject)
{
#if GS_WITH_GC
return NO;
#else /* GS_WITH_GC */
if (double_release_check_enabled)
{
unsigned release_count;
unsigned retain_count = [anObject retainCount];
release_count = [autorelease_class autoreleaseCountForObject: anObject];
if (release_count >= retain_count)
[NSException raise: NSGenericException
format: @"Release would release object too many times."];
}
#if defined(REFCNT_LOCAL)
if (allocationLock != 0)
{
@ -696,20 +719,6 @@ NSShouldRetainWithZone (NSObject *anObject, NSZone *requestedZone)
/* The Class responsible for handling autorelease's. This does not
need mutex protection, since it is simply a pointer that gets read
and set. */
static id autorelease_class = nil;
static SEL autorelease_sel;
static IMP autorelease_imp;
/* When this is `YES', every call to release/autorelease, checks to
make sure isn't being set up to release itself too many times.
This does not need mutex protection. */
static BOOL double_release_check_enabled = NO;
struct objc_method_description_list {
int count;
struct objc_method_description list[1];
@ -1828,16 +1837,6 @@ GSDescriptionForClassMethod(pcl self, SEL aSel)
- (oneway void) release
{
#if GS_WITH_GC == 0
if (double_release_check_enabled)
{
unsigned release_count;
unsigned retain_count = [self retainCount];
release_count = [autorelease_class autoreleaseCountForObject:self];
if (release_count >= retain_count)
[NSException raise: NSGenericException
format: @"Release would release object too many times."];
}
if (NSDecrementExtraRefCountWasZero(self))
{
[self dealloc];