Masses of fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@5474 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-12-13 12:14:01 +00:00
parent b35bbfad7e
commit 22f09ca318
8 changed files with 666 additions and 483 deletions

View file

@ -1,3 +1,22 @@
Mon Dec 13 12:20:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Fixes for cball's changes (who is cball?, and why didn't s/he produce
a ChangeLog entry or conform to GNU indentation? It took me hours to
tidy this up).
* Source/NSDate.m: ([NSGDate -addTimeInterval:]) removed bogus
implementation of method (inherits from NSDate).
* Source/NSCalendarDate.m: Added implementation of ([-addTimeInterval:])
with specific code for NSCalendarDate. Reformatted code to GNUstep
style.
* Source/NSGArray.m: ([-removeObjectIdenticalTo:]) and
([-removeObjectIdenticalTo:inRange:]) reverted to correct code.
([-removeObject:]) and ([-removeObjectIdenticalTo:inRange:]) removed
changes and added fixes so that methods are safe where multiple objects
equal to the object to be removed are present in the array.
* Source/NSArray.m: Similar fixes for object removal.
* Source/NSObject.m: Rewritten mutex code so that mutexes are not used
for retain/release unless the app is multi-threaded.
Wed Dec 1 19:36:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk> Wed Dec 1 19:36:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSArray.m: When sorting, treat illegal return values from the * Source/NSArray.m: When sorting, treat illegal return values from the

View file

@ -898,13 +898,10 @@ static NSString *indentStrings[] = {
if (o == anObject) if (o == anObject)
{ {
if (rem == 0) if (rem == 0)
{
rem = [self methodForSelector: remSel]; rem = [self methodForSelector: remSel];
}
(*rem)(self, remSel, i); (*rem)(self, remSel, i);
/*
* Bail out now or run the risk of comparing against a garbage
* pointer.
*/
return;
} }
} }
} }
@ -942,15 +939,24 @@ static NSString *indentStrings[] = {
if (o == anObject || (*eq)(anObject, eqSel, o) == YES) if (o == anObject || (*eq)(anObject, eqSel, o) == YES)
{ {
if (rem == 0) if (rem == 0)
{
rem = [self methodForSelector: remSel]; rem = [self methodForSelector: remSel];
(*rem)(self, remSel, i);
/* /*
* Bail out now or run the risk of comparing against a garbage * We need to retain the object so that when we remove the
* pointer. * first equal object we don't get left with a bad object
* pointer for later comparisons.
*/ */
return; RETAIN(anObject);
}
(*rem)(self, remSel, i);
} }
} }
#ifndef GS_WITH_GC
if (rem != 0)
{
RELEASE(anObject);
}
#endif
} }
} }
@ -984,13 +990,10 @@ static NSString *indentStrings[] = {
if (o == anObject) if (o == anObject)
{ {
if (rem == 0) if (rem == 0)
{
rem = [self methodForSelector: remSel]; rem = [self methodForSelector: remSel];
}
(*rem)(self, remSel, i); (*rem)(self, remSel, i);
/*
* Bail out now or run the risk of comparing against a garbage
* pointer.
*/
return;
} }
} }
} }
@ -1020,15 +1023,24 @@ static NSString *indentStrings[] = {
if (o == anObject || (*eq)(anObject, eqSel, o) == YES) if (o == anObject || (*eq)(anObject, eqSel, o) == YES)
{ {
if (rem == 0) if (rem == 0)
{
rem = [self methodForSelector: remSel]; rem = [self methodForSelector: remSel];
(*rem)(self, remSel, i);
/* /*
* Bail out now or run the risk of comparing against a garbage * We need to retain the object so that when we remove the
* pointer. * first equal object we don't get left with a bad object
* pointer for later comparisons.
*/ */
return; RETAIN(anObject);
}
(*rem)(self, remSel, i);
} }
} }
#ifndef GS_WITH_GC
if (rem != 0)
{
RELEASE(anObject);
}
#endif
} }
} }
@ -1041,9 +1053,11 @@ static NSString *indentStrings[] = {
IMP remLast = [self methodForSelector: rlSel]; IMP remLast = [self methodForSelector: rlSel];
while (c--) while (c--)
{
(*remLast)(self, rlSel); (*remLast)(self, rlSel);
} }
} }
}
- (void) addObjectsFromArray: (NSArray*)otherArray - (void) addObjectsFromArray: (NSArray*)otherArray
{ {
@ -1149,9 +1163,11 @@ static NSString *indentStrings[] = {
IMP rem = [self methodForSelector: remSel]; IMP rem = [self methodForSelector: remSel];
while (i-- > s) while (i-- > s)
{
(*rem)(self, remSel, i); (*rem)(self, remSel, i);
} }
} }
}
- (void) sortUsingSelector: (SEL)comparator - (void) sortUsingSelector: (SEL)comparator
{ {

View file

@ -117,6 +117,16 @@
return AUTORELEASE(d); return AUTORELEASE(d);
} }
- (id) addTimeInterval: (NSTimeInterval)seconds
{
id newObj = [[self class] dateWithTimeIntervalSinceReferenceDate:
[self timeIntervalSinceReferenceDate] + seconds];
[newObj setTimeZone: [self timeZoneDetail]];
return newObj;
}
- (Class) classForPortCoder - (Class) classForPortCoder
{ {
return [self class]; return [self class];
@ -129,14 +139,16 @@
- (void) encodeWithCoder: (NSCoder*)coder - (void) encodeWithCoder: (NSCoder*)coder
{ {
[coder encodeValueOfObjCType: @encode(NSTimeInterval) at: &_seconds_since_ref]; [coder encodeValueOfObjCType: @encode(NSTimeInterval)
at: &_seconds_since_ref];
[coder encodeObject: _calendar_format]; [coder encodeObject: _calendar_format];
[coder encodeObject: _time_zone]; [coder encodeObject: _time_zone];
} }
- (id) initWithCoder: (NSCoder*)coder - (id) initWithCoder: (NSCoder*)coder
{ {
[coder decodeValueOfObjCType: @encode(NSTimeInterval) at: &_seconds_since_ref]; [coder decodeValueOfObjCType: @encode(NSTimeInterval)
at: &_seconds_since_ref];
[coder decodeValueOfObjCType: @encode(id) at: &_calendar_format]; [coder decodeValueOfObjCType: @encode(id) at: &_calendar_format];
[coder decodeValueOfObjCType: @encode(id) at: &_time_zone]; [coder decodeValueOfObjCType: @encode(id) at: &_time_zone];
return self; return self;
@ -176,18 +188,15 @@
{ {
int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0; int year = 0, month = 1, day = 1, hour = 0, min = 0, sec = 0;
NSTimeZone *tz = [NSTimeZone localTimeZone]; NSTimeZone *tz = [NSTimeZone localTimeZone];
BOOL ampm = NO;
int ampm = 0, twelveHrClock = 0; BOOL twelveHrClock = NO;
int julianWeeks = -1, weekStartsMonday = 0, dayOfWeek = -1; int julianWeeks = -1, weekStartsMonday = 0, dayOfWeek = -1;
const char *source = [description cString]; const char *source = [description cString];
int sourceLen = strlen(source); int sourceLen = strlen(source);
const char *format = [fmt cString]; const char *format = [fmt cString];
int formatLen = strlen(format); int formatLen = strlen(format);
int formatIdx = 0; int formatIdx = 0;
int sourceIdx = 0; int sourceIdx = 0;
char tmpStr[20]; char tmpStr[20];
int tmpIdx; int tmpIdx;
@ -236,14 +245,16 @@
// %Y year as a decimal number with century // %Y year as a decimal number with century
// %z time zone offset in hours and minutes from GMT (HHMM) // %z time zone offset in hours and minutes from GMT (HHMM)
// %Z time zone abbreviation // %Z time zone abbreviation
while (formatIdx < formatLen) while (formatIdx < formatLen)
{ {
if (format[formatIdx] != '%') if (format[formatIdx] != '%')
{ {
// If it's not a format specifier, ignore it. // If it's not a format specifier, ignore it.
sourceIdx++; sourceIdx++;
} else { }
else
{
// Skip '%' // Skip '%'
formatIdx++; formatIdx++;
@ -261,12 +272,19 @@
tmpStr[2] = tolower(source[sourceIdx++]); tmpStr[2] = tolower(source[sourceIdx++]);
tmpStr[3] = '\0'; tmpStr[3] = '\0';
{ {
NSString *currDay = [NSString stringWithCString: tmpStr]; NSString *currDay;
NSArray *dayNames = [locale objectForKey: NSShortWeekDayNameArray]; NSArray *dayNames;
currDay = [NSString stringWithCString: tmpStr];
dayNames = [locale objectForKey: NSShortWeekDayNameArray];
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++) for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay] == YES) {
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay]
== YES)
{
break; break;
}
}
dayOfWeek = tmpIdx; dayOfWeek = tmpIdx;
} }
break; break;
@ -277,19 +295,28 @@
if (isalpha(source[tmpIdx])) if (isalpha(source[tmpIdx]))
{ {
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx]; tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
} else { }
else
{
break; break;
} }
} }
tmpStr[tmpIdx - sourceIdx] = '\0'; tmpStr[tmpIdx - sourceIdx] = '\0';
sourceIdx += tmpIdx - sourceIdx; sourceIdx += tmpIdx - sourceIdx;
{ {
NSString *currDay = [NSString stringWithCString: tmpStr]; NSString *currDay;
NSArray *dayNames = [locale objectForKey: NSWeekDayNameArray]; NSArray *dayNames;
currDay = [NSString stringWithCString: tmpStr];
dayNames = [locale objectForKey: NSWeekDayNameArray];
for (tmpIdx = 0; tmpIdx < 7; tmpIdx++) for (tmpIdx = 0; tmpIdx < 7; tmpIdx++)
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay] == YES) {
if ([[dayNames objectAtIndex: tmpIdx] isEqual: currDay]
== YES)
{
break; break;
}
}
dayOfWeek = tmpIdx; dayOfWeek = tmpIdx;
} }
break; break;
@ -301,14 +328,20 @@
tmpStr[2] = tolower(source[sourceIdx++]); tmpStr[2] = tolower(source[sourceIdx++]);
tmpStr[3] = '\0'; tmpStr[3] = '\0';
{ {
NSString *currMonth = [NSString stringWithCString: tmpStr]; NSString *currMonth;
NSArray *monthNames = [locale objectForKey: NSShortMonthNameArray]; NSArray *monthNames;
currMonth = [NSString stringWithCString: tmpStr];
monthNames = [locale objectForKey: NSShortMonthNameArray];
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++) for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
{ {
if ([[monthNames objectAtIndex: tmpIdx] isEqual: currMonth] == YES) if ([[monthNames objectAtIndex: tmpIdx]
isEqual: currMonth] == YES)
{
break; break;
} }
}
month = tmpIdx+1; month = tmpIdx+1;
} }
break; break;
@ -319,21 +352,30 @@
if (isalpha(source[tmpIdx])) if (isalpha(source[tmpIdx]))
{ {
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx]; tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
} else { }
else
{
break; break;
} }
} }
tmpStr[tmpIdx - sourceIdx] = '\0'; tmpStr[tmpIdx - sourceIdx] = '\0';
sourceIdx += tmpIdx - sourceIdx; sourceIdx += tmpIdx - sourceIdx;
{ {
NSString *currMonth = [NSString stringWithCString: tmpStr]; NSString *currMonth;
NSArray *monthNames = [locale objectForKey: NSMonthNameArray]; NSArray *monthNames;
currMonth = [NSString stringWithCString: tmpStr];
monthNames = [locale objectForKey: NSMonthNameArray];
for (tmpIdx = 0; tmpIdx < 12; tmpIdx++) for (tmpIdx = 0; tmpIdx < 12; tmpIdx++)
if ([[monthNames objectAtIndex: tmpIdx] isEqual: currMonth] == YES) {
if ([[monthNames objectAtIndex: tmpIdx]
isEqual: currMonth] == YES)
{
break; break;
}
}
month = tmpIdx+1; month = tmpIdx+1;
} }
break; break;
@ -352,7 +394,7 @@
// break; // break;
case 'I': // fall through case 'I': // fall through
twelveHrClock = 1; twelveHrClock = YES;
case 'H': case 'H':
memcpy(tmpStr, &source[sourceIdx], 2); memcpy(tmpStr, &source[sourceIdx], 2);
tmpStr[2] = '\0'; tmpStr[2] = '\0';
@ -388,16 +430,20 @@
tmpStr[1] = toupper(source[sourceIdx++]); tmpStr[1] = toupper(source[sourceIdx++]);
tmpStr[2] = '\0'; tmpStr[2] = '\0';
{ {
NSString *currAMPM = [NSString stringWithCString: tmpStr]; NSString *currAMPM;
NSArray *amPMNames = [locale objectForKey: NSAMPMDesignation]; NSArray *amPMNames;
currAMPM = [NSString stringWithCString: tmpStr];
amPMNames = [locale objectForKey: NSAMPMDesignation];
/* /*
* The time addition is handled below because this * The time addition is handled below because this
* indicator only modifies the time on a 12hour clock. * indicator only modifies the time on a 12hour clock.
*/ */
if ([[amPMNames objectAtIndex: 1] isEqual: currAMPM] == YES) if ([[amPMNames objectAtIndex: 1] isEqual: currAMPM] == YES)
ampm = 1; {
ampm = YES;
}
} }
break; break;
@ -437,7 +483,9 @@
if (year >= 70) if (year >= 70)
{ {
year += 1900; year += 1900;
} else { }
else
{
year += 2000; year += 2000;
} }
break; break;
@ -456,8 +504,8 @@
tmpStr[3] = tolower(source[sourceIdx++]); tmpStr[3] = tolower(source[sourceIdx++]);
tmpStr[4] = '\0'; tmpStr[4] = '\0';
{ {
int zone; int zone = atoi(tmpStr);
zone = atoi( tmpStr );
if ((tz = [NSTimeZone timeZoneForSecondsFromGMT: if ((tz = [NSTimeZone timeZoneForSecondsFromGMT:
(zone / 100 * 60 + (zone % 100)) * 60]) == nil) (zone / 100 * 60 + (zone % 100)) * 60]) == nil)
{ {
@ -469,10 +517,13 @@
case 'Z': case 'Z':
for (tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++) for (tmpIdx = sourceIdx; tmpIdx < sourceLen; tmpIdx++)
{ {
if ( isalpha( source[tmpIdx] ) || source[tmpIdx] == '-' || source[tmpIdx] == '+' ) if (isalpha(source[tmpIdx]) || source[tmpIdx] == '-'
|| source[tmpIdx] == '+')
{ {
tmpStr[tmpIdx - sourceIdx] = source[tmpIdx]; tmpStr[tmpIdx - sourceIdx] = source[tmpIdx];
} else { }
else
{
break; break;
} }
} }
@ -488,17 +539,16 @@
break; break;
default: default:
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException format:
format: @"Invalid NSCalendar date, specifier %c not recognized in format %s", @"Invalid NSCalendar date, specifier %c not recognized in format %s", format[formatIdx], format];
format[formatIdx], format];
} }
} }
formatIdx++; formatIdx++;
} }
if ( twelveHrClock ) if (twelveHrClock == YES)
{ {
if ( ampm && hour != 12 ) if (ampm == YES && hour != 12)
{ {
hour += 12; hour += 12;
} }
@ -506,8 +556,19 @@
if (julianWeeks != -1) if (julianWeeks != -1)
{ {
int currDay = [[[[NSCalendarDate alloc] initWithYear: year month: 1 day: 1 hour: 0 minute: 0 NSTimeZone *gmtZone;
second: 0 timeZone: [NSTimeZone timeZoneForSecondsFromGMT: 0]] autorelease] dayOfWeek]; NSCalendarDate *d;
int currDay;
gmtZone = [NSTimeZone timeZoneForSecondsFromGMT: 0];
d = [NSCalendarDate dateWithYear: year
month: 1
day: 1
hour: 0
minute: 0
second: 0
timeZone: gmtZone];
currDay = [d dayOfWeek];
/* /*
* The julian weeks are either sunday relative or monday relative but all * The julian weeks are either sunday relative or monday relative but all
@ -519,15 +580,21 @@
if (weekStartsMonday) if (weekStartsMonday)
{ {
dayOfWeek = 1; dayOfWeek = 1;
} else { }
else
{
dayOfWeek = 0; dayOfWeek = 0;
} }
} }
day = dayOfWeek + (julianWeeks * 7 - (currDay - 1)); day = dayOfWeek + (julianWeeks * 7 - (currDay - 1));
} }
return [[NSCalendarDate alloc] initWithYear: year month: month day: day hour: hour return [[NSCalendarDate alloc] initWithYear: year
minute: min second: sec month: month
day: day
hour: hour
minute: min
second: sec
timeZone: tz]; timeZone: tz];
} }

View file

@ -1115,18 +1115,6 @@ GSTimeNow()
// Adding and getting intervals // Adding and getting intervals
- (id) addTimeInterval: (NSTimeInterval)seconds
{
/* xxx We need to check for overflow? */
id newObj = [[self class] dateWithTimeIntervalSinceReferenceDate:
_seconds_since_ref + seconds];
if ([self isKindOfClass: [NSCalendarDate class]])
[newObj setTimeZone: [(NSCalendarDate *) self timeZoneDetail]];
return newObj;
}
- (NSTimeInterval) timeIntervalSince1970 - (NSTimeInterval) timeIntervalSince1970
{ {
return _seconds_since_ref - UNIX_REFERENCE_INTERVAL; return _seconds_since_ref - UNIX_REFERENCE_INTERVAL;

View file

@ -433,16 +433,25 @@ static SEL eqSel = @selector(isEqual:);
if (index > 0) if (index > 0)
{ {
BOOL (*imp)(id,SEL,id); BOOL (*imp)(id,SEL,id);
#if GS_WITH_GC == 0
BOOL retained = NO;
#endif
imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: eqSel]; imp = (BOOL (*)(id,SEL,id))[anObject methodForSelector: eqSel];
while (index-- > 0) while (index-- > 0)
{ {
if ((*imp)(anObject, eqSel, _contents_array[index]) == YES) if ((*imp)(anObject, eqSel, _contents_array[index]) == YES)
{ {
unsigned pos = index;
#if GS_WITH_GC == 0 #if GS_WITH_GC == 0
id obj = _contents_array[index]; id obj = _contents_array[index];
if (retained == NO)
{
RETAIN(anObject);
retained = YES;
}
#endif #endif
unsigned pos = index;
while (++pos < _count) while (++pos < _count)
{ {
@ -450,13 +459,14 @@ static SEL eqSel = @selector(isEqual:);
} }
_count--; _count--;
RELEASE(obj); RELEASE(obj);
/*
* Bail out now or run the risk of comparing against a garbage
* pointer.
*/
return;
} }
} }
#if GS_WITH_GC == 0
if (retained == YES)
{
RELEASE(anObject);
}
#endif
} }
} }
@ -505,11 +515,6 @@ static SEL eqSel = @selector(isEqual:);
} }
_count--; _count--;
RELEASE(obj); RELEASE(obj);
/*
* Bail out now or run the risk of comparing against a garbage
* pointer.
*/
return;
} }
} }
} }

View file

@ -99,7 +99,9 @@ NSString *NSRecursiveLockException = @"NSRecursiveLockException";
if (objc_mutex_trylock(_mutex) == -1) if (objc_mutex_trylock(_mutex) == -1)
{ {
return NO; return NO;
} else { }
else
{
/* /*
* The recursive lock check goes here to support openstep's * The recursive lock check goes here to support openstep's
* implementation. In openstep you can lock in one thread trylock in the * implementation. In openstep you can lock in one thread trylock in the

View file

@ -39,6 +39,8 @@
#include <Foundation/NSDistantObject.h> #include <Foundation/NSDistantObject.h>
#include <Foundation/NSZone.h> #include <Foundation/NSZone.h>
#include <Foundation/NSDebug.h> #include <Foundation/NSDebug.h>
#include <Foundation/NSThread.h>
#include <Foundation/NSNotification.h>
#include <limits.h> #include <limits.h>
#include <base/fast.x> #include <base/fast.x>
@ -103,6 +105,12 @@ void _fastBuildCache()
* correct zone to free memory very fast. * correct zone to free memory very fast.
*/ */
/*
* retain_counts_gate is needed when running multi-threaded for retain/release
* to work reliably.
*/
static objc_mutex_t retain_counts_gate = NULL;
#if GS_WITH_GC == 0 #if GS_WITH_GC == 0
#define REFCNT_LOCAL 1 #define REFCNT_LOCAL 1
#define CACHE_ZONE 1 #define CACHE_ZONE 1
@ -182,34 +190,63 @@ NSExtraRefCount(id anObject)
return ((obj)anObject)[-1].retained; return ((obj)anObject)[-1].retained;
} }
static objc_mutex_t retain_counts_gate = NULL;
void void
NSIncrementExtraRefCount(id anObject) NSIncrementExtraRefCount(id anObject)
{
if (retain_counts_gate != 0)
{ {
objc_mutex_lock(retain_counts_gate); objc_mutex_lock(retain_counts_gate);
((obj)anObject)[-1].retained++; ((obj)anObject)[-1].retained++;
objc_mutex_unlock (retain_counts_gate); objc_mutex_unlock (retain_counts_gate);
} }
else
{
((obj)anObject)[-1].retained++;
}
}
#define NSIncrementExtraRefCount(X) \ #define NSIncrementExtraRefCount(X) ({ \
if (retain_counts_gate != 0) \
{ \
objc_mutex_lock(retain_counts_gate); \ objc_mutex_lock(retain_counts_gate); \
((obj)(X))[-1].retained++; \ ((obj)(X))[-1].retained++; \
objc_mutex_unlock (retain_counts_gate) objc_mutex_unlock(retain_counts_gate); \
} \
else \
{ \
((obj)X)[-1].retained++; \
} \
})
BOOL BOOL
NSDecrementExtraRefCountWasZero(id anObject) NSDecrementExtraRefCountWasZero(id anObject)
{
if (retain_counts_gate != 0)
{ {
objc_mutex_lock(retain_counts_gate); objc_mutex_lock(retain_counts_gate);
if (((obj)anObject)[-1].retained-- == 0) if (((obj)anObject)[-1].retained-- == 0)
{ {
objc_mutex_unlock(retain_counts_gate); objc_mutex_unlock(retain_counts_gate);
return YES; return YES;
} else { }
else
{
objc_mutex_unlock(retain_counts_gate); objc_mutex_unlock(retain_counts_gate);
return NO; return NO;
} }
} }
else
{
if (((obj)anObject)[-1].retained-- == 0)
{
return YES;
}
else
{
return NO;
}
}
}
#define NSExtraRefCount(X) (((obj)(X))[-1].retained) #define NSExtraRefCount(X) (((obj)(X))[-1].retained)
@ -218,8 +255,6 @@ NSDecrementExtraRefCountWasZero(id anObject)
/* The maptable of retain counts on objects */ /* The maptable of retain counts on objects */
static o_map_t *retain_counts = NULL; static o_map_t *retain_counts = NULL;
/* The mutex lock to protect multi-threaded use of `retain_counts' */
static objc_mutex_t retain_counts_gate = NULL;
void void
NSIncrementExtraRefCount (id anObject) NSIncrementExtraRefCount (id anObject)
@ -227,6 +262,8 @@ NSIncrementExtraRefCount (id anObject)
o_map_node_t *node; o_map_node_t *node;
extern o_map_node_t *o_map_node_for_key(o_map_t *m, const void *k); extern o_map_node_t *o_map_node_for_key(o_map_t *m, const void *k);
if (retain_counts_gate != 0)
{
objc_mutex_lock(retain_counts_gate); objc_mutex_lock(retain_counts_gate);
node = o_map_node_for_key (retain_counts, anObject); node = o_map_node_for_key (retain_counts, anObject);
if (node) if (node)
@ -235,6 +272,15 @@ NSIncrementExtraRefCount (id anObject)
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1); o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
objc_mutex_unlock(retain_counts_gate); objc_mutex_unlock(retain_counts_gate);
} }
else
{
node = o_map_node_for_key (retain_counts, anObject);
if (node)
((int)(node->value))++;
else
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
}
}
BOOL BOOL
NSDecrementExtraRefCountWasZero (id anObject) NSDecrementExtraRefCountWasZero (id anObject)
@ -243,6 +289,8 @@ NSDecrementExtraRefCountWasZero (id anObject)
extern o_map_node_t *o_map_node_for_key (o_map_t *m, const void *k); extern o_map_node_t *o_map_node_for_key (o_map_t *m, const void *k);
extern void o_map_remove_node (o_map_node_t *node); extern void o_map_remove_node (o_map_node_t *node);
if (retain_counts_gate != 0)
{
objc_mutex_lock(retain_counts_gate); objc_mutex_lock(retain_counts_gate);
node = o_map_node_for_key (retain_counts, anObject); node = o_map_node_for_key (retain_counts, anObject);
if (!node) if (!node)
@ -252,8 +300,24 @@ NSDecrementExtraRefCountWasZero (id anObject)
} }
NSAssert((int)(node->value) > 0, NSInternalInconsistencyException); NSAssert((int)(node->value) > 0, NSInternalInconsistencyException);
if (!--((int)(node->value))) if (!--((int)(node->value)))
{
o_map_remove_node (node); o_map_remove_node (node);
}
objc_mutex_unlock(retain_counts_gate); objc_mutex_unlock(retain_counts_gate);
}
else
{
node = o_map_node_for_key (retain_counts, anObject);
if (!node)
{
return YES;
}
NSAssert((int)(node->value) > 0, NSInternalInconsistencyException);
if (!--((int)(node->value)))
{
o_map_remove_node (node);
}
}
return NO; return NO;
} }
@ -262,11 +326,26 @@ NSExtraRefCount (id anObject)
{ {
unsigned ret; unsigned ret;
if (retain_counts_gate != 0)
{
objc_mutex_lock(retain_counts_gate); objc_mutex_lock(retain_counts_gate);
ret = (unsigned) o_map_value_at_key(retain_counts, anObject); ret = (unsigned) o_map_value_at_key(retain_counts, anObject);
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts) || if (ret == (unsigned)o_map_not_a_key_marker(retain_counts)
ret == (unsigned)o_map_not_a_value_marker(retain_counts)) ret = 0; || ret == (unsigned)o_map_not_a_value_marker(retain_counts))
{
ret = 0;
}
objc_mutex_unlock(retain_counts_gate); objc_mutex_unlock(retain_counts_gate);
}
else
{
ret = (unsigned) o_map_value_at_key(retain_counts, anObject);
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts)
|| ret == (unsigned)o_map_not_a_value_marker(retain_counts))
{
ret = 0;
}
}
return ret; /* ExtraRefCount + 1 */ return ret; /* ExtraRefCount + 1 */
} }
@ -501,9 +580,18 @@ static IMP autorelease_imp = 0;
This does not need mutex protection. */ This does not need mutex protection. */
static BOOL double_release_check_enabled = NO; static BOOL double_release_check_enabled = NO;
@implementation NSObject @implementation NSObject
+ (void) _becomeMultiThreaded: (NSNotification)aNotification
{
if (retain_counts_gate == 0)
{
retain_counts_gate = objc_mutex_allocate();
}
}
+ (void) initialize + (void) initialize
{ {
if (self == [NSObject class]) if (self == [NSObject class])
@ -529,16 +617,16 @@ static BOOL double_release_check_enabled = NO;
retain_counts = o_map_with_callbacks (o_callbacks_for_non_owned_void_p, retain_counts = o_map_with_callbacks (o_callbacks_for_non_owned_void_p,
o_callbacks_for_int); o_callbacks_for_int);
#endif #endif
/*
* retain_counts_gate is needed on SMP machines for release to work
* reliably.
*/
retain_counts_gate = objc_mutex_allocate ();
fastMallocOffset = fastMallocClass->instance_size % ALIGN; fastMallocOffset = fastMallocClass->instance_size % ALIGN;
#else #else
fastMallocOffset = 0; fastMallocOffset = 0;
#endif #endif
_fastBuildCache(); _fastBuildCache();
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_becomeMultiThreaded:)
name: NSWillBecomeMultiThreadedNotification
object: nil];
} }
return; return;
} }
@ -674,13 +762,13 @@ static BOOL double_release_check_enabled = NO;
- (NSString*) description - (NSString*) description
{ {
return [NSString stringWithFormat: @"<%s %lx>", return [NSString stringWithFormat: @"<%s: %lx>",
object_get_class_name(self), (unsigned long)self]; object_get_class_name(self), (unsigned long)self];
} }
+ (NSString*) description + (NSString*) description
{ {
return [NSString stringWithFormat: @"<%s>", object_get_class_name(self)]; return [NSString stringWithCString: object_get_class_name(self)];
} }
- (void) descriptionTo: (id<GNUDescriptionDestination>)output - (void) descriptionTo: (id<GNUDescriptionDestination>)output
@ -781,7 +869,7 @@ static BOOL double_release_check_enabled = NO;
/* NSObject protocol */ /* NSObject protocol */
- autorelease - (id) autorelease
{ {
#if GS_WITH_GC == 0 #if GS_WITH_GC == 0
if (double_release_check_enabled) if (double_release_check_enabled)

View file

@ -972,19 +972,17 @@ static NSMapTable *absolutes = 0;
+ (NSString*) getTimeZoneFile: (NSString *)name + (NSString*) getTimeZoneFile: (NSString *)name
{ {
/* NSString *fileName = [NSString stringWithFormat: @"%@%@", ZONES_DIR, name];
* OpenStep does NOT put all the GMT+-* timezones in the Etc directory so all
* the OpenStep software will fail to work without this extra hack.
*/
NSString *fileName = [NSString stringWithFormat: @"%@%@",
ZONES_DIR, name];
NSString *path = [NSBundle pathForGNUstepResource: fileName NSString *path = [NSBundle pathForGNUstepResource: fileName
ofType: @"" ofType: @""
inDirectory: TIME_ZONE_DIR]; inDirectory: TIME_ZONE_DIR];
if ( !path ) /*
* Hack for OPENSTEP storing zones in Etc?
*/
if (path == nil)
{ {
return [self getTimeZoneFile: [NSString stringWithFormat: @"Etc/%@", name]]; path=[self getTimeZoneFile: [NSString stringWithFormat: @"Etc/%@", name]];
} }
return path; return path;
} }