Optimisation, bug fixes and tidying up.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4107 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-04-21 20:16:25 +00:00
parent 4b1b047b85
commit bad4f54d67
14 changed files with 302 additions and 255 deletions

View file

@ -1,3 +1,19 @@
Wed Apr 21 20:25:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSAttributedString.m: Tidied.
* Source/Source/NSAutoreleasePool.m: Thread exit code added
* Source/NSCalendarDate.m: Tidied
* Source/NSConnection.m: ditto
* Source/NSException.m: Tidied and added description
* Source/NSRunLoop.m: Optimisation, bugfixes, and removal of cruft.
* Source/NSThread.m: Clean up autorelease pools on exit.
* Source/NSTimer.m: Optimise use in runloop.
* Source/include/FastArray.x: Bugfix for sorted array.
* Source/include/NSAutoreleasePool.h: Mod for threads.
* Source/include/NSObject.h: More retain/release macros.
* Source/include/NSRunLoop.h: Optimise limit date.
* Source/include/NSTimer.h: Optimise use with run loop.
Tue Apr 20 16:50:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/Makefile.postamble: NSRunLoop.m uses FastArray.x

View file

@ -38,7 +38,7 @@
#define FAST_ARRAY_CHECK NSCAssert(array->count <= array->cap && array->old <= array->cap && array->old >= 1, NSInternalInconsistencyException)
/*
* This file should be INCLUDED in files wanting to use the FastArray
This file should be INCLUDED in files wanting to use the FastArray
* functions - these are all declared inline for maximum performance.
*
* The file including this one may predefine some macros to alter
@ -113,6 +113,12 @@ struct _FastArray {
typedef struct _FastArray FastArray_t;
typedef struct _FastArray *FastArray;
static INLINE unsigned
FastArrayCount(FastArray array)
{
return array->count;
}
static INLINE void
FastArrayGrow(FastArray array)
{
@ -210,13 +216,13 @@ static INLINE unsigned
FastArrayInsertionPosition(FastArray array, FastArrayItem item, int (*sorter)())
{
unsigned upper = array->count;
unsigned index = upper/2;
unsigned lower = 0;
unsigned index;
/*
* Binary search for an item equal to the one to be inserted.
*
while (upper != lower)
*/
for (index = upper/2; upper != lower; index = lower+(upper-lower)/2)
{
int comparison = (*sorter)(item, array->ptr[index]);
@ -232,7 +238,6 @@ FastArrayInsertionPosition(FastArray array, FastArrayItem item, int (*sorter)())
{
break;
}
index = lower+(upper-lower)/2;
}
/*
* Now skip past any equal items so the insertion point is AFTER any
@ -242,9 +247,24 @@ FastArrayInsertionPosition(FastArray array, FastArrayItem item, int (*sorter)())
{
index++;
}
NSCAssert(index <= array->count, NSInternalInconsistencyException);
return index;
}
#ifndef NS_BLOCK_ASSERTIONS
static INLINE void
FastArrayCheckSort(FastArray array, int (*sorter)())
{
unsigned i;
for (i = 1; i < FastArrayCount(array); i++)
{
NSCAssert(((*sorter)(array->ptr[i-1], array->ptr[i]) <= 0),
NSInvalidArgumentException);
}
}
#endif
static INLINE void
FastArrayInsertSorted(FastArray array, FastArrayItem item, int (*sorter)())
{
@ -252,6 +272,21 @@ FastArrayInsertSorted(FastArray array, FastArrayItem item, int (*sorter)())
index = FastArrayInsertionPosition(array, item, sorter);
FastArrayInsertItem(array, item, index);
#ifndef NS_BLOCK_ASSERTIONS
FastArrayCheckSort(array, sorter);
#endif
}
static INLINE void
FastArrayInsertSortedNoRetain(FastArray array, FastArrayItem item, int (*sorter)())
{
unsigned index;
index = FastArrayInsertionPosition(array, item, sorter);
FastArrayInsertItemNoRetain(array, item, index);
#ifndef NS_BLOCK_ASSERTIONS
FastArrayCheckSort(array, sorter);
#endif
}
static INLINE void
@ -295,12 +330,6 @@ FastArrayItemAtIndex(FastArray array, unsigned index)
return array->ptr[index];
}
static INLINE unsigned
FastArrayCount(FastArray array)
{
return array->count;
}
static INLINE void
FastArrayClear(FastArray array)
{

View file

@ -90,6 +90,7 @@ struct autorelease_array_list
+ (void) enableRelease: (BOOL)enable;
+ (void) setPoolCountThreshhold: (unsigned)c;
+ (unsigned) autoreleaseCountForObject: anObject;
+ (void) _endThread; /* Don't call this directly - NSThread uses it. */
/*
* The next two methods have no effect unless you define COUNT_ALL to be
* 1 in NSAutoreleasepool.m - doing so incurs a thread lookup overhead

View file

@ -230,6 +230,10 @@ extern NSRecursiveLock *gnustep_global_lock;
#define RELEASE(object)
#define AUTORELEASE(object) ((id)object)
#define TEST_RETAIN(object) ((id)object)
#define TEST_RELEASE(object)
#define TEST_AUTORELEASE(object) ((id)object)
#define ASSIGN(object,value) (object = value)
#define ASSIGNCOPY(object,value) (object = [value copy])
#define DESTROY(object) (object = nil)
@ -238,10 +242,21 @@ extern NSRecursiveLock *gnustep_global_lock;
#else
/*
* Basic retain, release, and autorelease operations.
*/
#define RETAIN(object) [object retain]
#define RELEASE(object) [object release]
#define AUTORELEASE(object) [object autorelease]
/*
* Tested retain, release, and autorelease operations - only invoke the
* objective-c method if the receiver is not nil.
*/
#define TEST_RETAIN(object) (object != nil ? [object retain] : nil)
#define TEST_RELEASE(object) ({ if (object) [object release]; })
#define TEST_AUTORELEASE(object) ({ if (object) [object autorelease]; })
/*
* ASSIGN(object,value) assignes the value to the object with
* appropriate retain and release operations.
@ -287,7 +302,13 @@ if (__value != object) \
* a nil pointer for tidyness - we can't accidentally use a DESTROYED
* object later.
*/
#define DESTROY(object) ([object release], object = nil)
#define DESTROY(object) ({ \
if (object) \
{ \
[object release]; \
object = nil; \
} \
})
#define CREATE_AUTORELEASE_POOL(X) \
NSAutoreleasePool *(X) = [NSAutoreleasePool new]

View file

@ -42,6 +42,7 @@ extern id NSDefaultRunLoopMode;
NSMutableArray *_timedPerformers;
NSMapTable *_rfdMap;
NSMapTable *_wfdMap;
NSDate *_limit;
}
+ (NSRunLoop*) currentRunLoop;

View file

@ -37,7 +37,7 @@
*/
@interface NSTimer : NSObject
{
NSDate *_date; /* Must be first - for NSRunLoop optimisation */
NSTimeInterval _date; /* Must be first - for NSRunLoop optimisation */
BOOL _invalidated; /* Must be 2nd - for NSRunLoop optimisation */
BOOL _repeats;
NSTimeInterval _interval;

View file

@ -135,7 +135,7 @@ static Class NSMutableAttributedString_concrete_class;
return [[[[self class] _concreteClass] allocWithZone: zone]
initWithAttributedString: self];
else
return [self retain];
return RETAIN(self);
}
//NSMutableCopying protocol
@ -392,10 +392,10 @@ static Class NSMutableAttributedString_concrete_class;
[m setAttributes: attrs range: rangeToSet];
}
newAttrString = [m copy];
[m release];
RELEASE(m);
}
[newAttrString autorelease];
AUTORELEASE(newAttrString);
return newAttrString;
}
@ -435,10 +435,10 @@ static Class NSMutableAttributedString_concrete_class;
tmpLength = [self length];
if (aRange.location <= 0 || NSMaxRange(aRange) > tmpLength)
{
[NSException raise: NSRangeException
format: @"RangeError in method -addAttribute: value: range: in class NSMutableAttributedString"];
}
{
[NSException raise: NSRangeException
format: @"RangeError in method -addAttribute: value: range: in class NSMutableAttributedString"];
}
attrDict = [self attributesAtIndex: aRange.location
effectiveRange: &effectiveRange];
@ -448,7 +448,7 @@ static Class NSMutableAttributedString_concrete_class;
effectiveRange = NSIntersectionRange(aRange,effectiveRange);
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
[newDict autorelease];
AUTORELEASE(newDict);
[newDict setObject: value forKey: name];
[self setAttributes: newDict range: effectiveRange];
@ -490,7 +490,7 @@ static Class NSMutableAttributedString_concrete_class;
effectiveRange = NSIntersectionRange(aRange,effectiveRange);
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
[newDict autorelease];
AUTORELEASE(newDict);
[newDict addEntriesFromDictionary: attributes];
[self setAttributes: newDict range: effectiveRange];
@ -526,7 +526,7 @@ static Class NSMutableAttributedString_concrete_class;
effectiveRange = NSIntersectionRange(aRange,effectiveRange);
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
[newDict autorelease];
AUTORELEASE(newDict);
[newDict removeObjectForKey: name];
[self setAttributes: newDict range: effectiveRange];
@ -617,7 +617,7 @@ static Class NSMutableAttributedString_concrete_class;
str = (GSMutableAttributedStringTracker*) NSAllocateObject(self, 0, z);
str->_owner = RETAIN(as);
return [str autorelease];
return AUTORELEASE(str);
}
- (void) dealloc

View file

@ -383,6 +383,29 @@ static IMP initImp;
return self;
}
+ (void) _endThread
{
struct autorelease_thread_vars *tv;
id pool;
tv = ARP_THREAD_VARS;
while (tv->current_pool)
{
[tv->current_pool release];
pool = pop_pool_from_cache(tv);
[pool reallyDealloc];
}
while (tv->pool_cache_count)
{
pool = pop_pool_from_cache(tv);
[pool reallyDealloc];
}
if (tv->pool_cache)
OBJC_FREE(tv->pool_cache);
}
+ (void) resetTotalAutoreleasedObjects
{
ARP_THREAD_VARS->total_objects_count = 0;

View file

@ -1006,19 +1006,22 @@
- (id) copyWithZone: (NSZone*)zone
{
NSCalendarDate *newDate;
NSCalendarDate *newDate;
if (NSShouldRetainWithZone(self, zone)) {
newDate = RETAIN(self);
if (NSShouldRetainWithZone(self, zone))
{
newDate = RETAIN(self);
}
else {
newDate = (NSCalendarDate*)NSCopyObject(self, 0, zone);
else
{
newDate = (NSCalendarDate*)NSCopyObject(self, 0, zone);
if (newDate) {
newDate->calendar_format = [calendar_format copyWithZone: zone];
if (newDate)
{
newDate->calendar_format = [calendar_format copyWithZone: zone];
}
}
return newDate;
return newDate;
}
- (NSString *)descriptionWithLocale: (NSDictionary *)locale

View file

@ -113,7 +113,7 @@ static unsigned local_object_counter = 0;
counter = (GSLocalCounter*)NSAllocateObject(self, 0, NSDefaultMallocZone());
counter->ref = 1;
counter->object = [obj retain];
counter->object = RETAIN(obj);
counter->target = ++local_object_counter;
return counter;
}
@ -149,7 +149,7 @@ static unsigned local_object_counter = 0;
{
CachedLocalObject *item = [[self alloc] init];
item->obj = [o retain];
item->obj = RETAIN(o);
item->time = t;
return [item autorelease];
}
@ -485,7 +485,8 @@ static int messages_received_count;
unsigned i;
[proxiesHashGate lock];
targets = [NSAllMapTableValues(local_targets) retain];
targets = NSAllMapTableValues(local_targets);
RETAIN(targets);
for (i = 0; i < [targets count]; i++)
{
id t = [[targets objectAtIndex:i] localForProxy];

View file

@ -1,5 +1,5 @@
/* NSException - Object encapsulation of a general exception handler
Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
Copyright (C) 1993, 1994, 1996, 1997, 1999 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@boulder.colorado.edu>
Date: Mar 1995
@ -10,7 +10,7 @@
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@ -33,106 +33,102 @@
static volatile void
_NSFoundationUncaughtExceptionHandler(NSException *exception)
{
fprintf(stderr, "Uncaught exception %s, reason: %s\n",
fprintf(stderr, "Uncaught exception %s, reason: %s\n",
[[exception name] cString], [[exception reason] cString]);
/* FIXME: need to implement this:
NSLogError("Uncaught exception %@, reason: %@",
NSLogError("Uncaught exception %@, reason: %@",
[exception name], [exception reason]);
*/
abort();
abort();
}
@implementation NSException
+ (NSException *)exceptionWithName:(NSString *)name
reason:(NSString *)reason
userInfo:(NSDictionary *)userInfo
+ (NSException*) exceptionWithName: (NSString *)name
reason: (NSString *)reason
userInfo: (NSDictionary *)userInfo
{
return [[[self alloc] initWithName:name reason:reason
userInfo:userInfo] autorelease];
return AUTORELEASE([[self alloc] initWithName: name reason: reason
userInfo: userInfo]);
}
+ (volatile void)raise:(NSString *)name
format:(NSString *)format,...
+ (volatile void) raise: (NSString *)name
format: (NSString *)format,...
{
va_list args;
va_list args;
va_start(args, format);
[self raise:name format:format arguments:args];
// FIXME: This probably doesn't matter, but va_end won't get called
va_end(args);
va_start(args, format);
[self raise: name format: format arguments: args];
// FIXME: This probably doesn't matter, but va_end won't get called
va_end(args);
}
+ (volatile void)raise:(NSString *)name
format:(NSString *)format
arguments:(va_list)argList
+ (volatile void) raise: (NSString *)name
format: (NSString *)format
arguments: (va_list)argList
{
NSString *reason;
NSException *except;
// OK?: not in OpenStep docs but is implmented by GNUStep
reason = [NSString stringWithFormat:format arguments:argList];
//reason = [[NSString alloc] initWithFormat:format arguments:argList];
//[reason autorelease];
except = [self exceptionWithName:name reason:reason userInfo:nil];
[except raise];
NSString *reason;
NSException *except;
reason = [NSString stringWithFormat: format arguments: argList];
except = [self exceptionWithName: name reason: reason userInfo: nil];
[except raise];
}
- (id)initWithName:(NSString *)name reason:(NSString *)reason
userInfo:(NSDictionary *)userInfo
- (id) initWithName: (NSString *)name
reason: (NSString *)reason
userInfo: (NSDictionary *)userInfo
{
self = [super init];
e_name = [name retain];
e_reason = [reason retain];
e_info = [userInfo retain];
return self;
ASSIGN(e_name, name);
ASSIGN(e_reason, reason);
ASSIGN(e_info, userInfo);
return self;
}
- (void)dealloc
{
[e_name release];
e_name = nil;
[e_reason release];
e_reason = nil;
[e_info release];
e_info = nil;
DESTROY(e_name);
DESTROY(e_reason);
DESTROY(e_info);
[super dealloc];
}
- (volatile void)raise
- (volatile void) raise
{
NSThread *thread;
NSHandler *handler;
if (_NSUncaughtExceptionHandler == NULL)
_NSUncaughtExceptionHandler = _NSFoundationUncaughtExceptionHandler;
NSThread *thread;
NSHandler *handler;
thread = GSCurrentThread();
handler = thread->_exception_handler;
if (handler == NULL) {
_NSUncaughtExceptionHandler(self);
return;
if (_NSUncaughtExceptionHandler == NULL)
{
_NSUncaughtExceptionHandler = _NSFoundationUncaughtExceptionHandler;
}
thread->_exception_handler = handler->next;
handler->exception = self;
longjmp(handler->jumpState, 1);
thread = GSCurrentThread();
handler = thread->_exception_handler;
if (handler == NULL)
{
_NSUncaughtExceptionHandler(self);
return;
}
thread->_exception_handler = handler->next;
handler->exception = self;
longjmp(handler->jumpState, 1);
}
- (NSString *)name
- (NSString *) name
{
return e_name;
return e_name;
}
- (NSString *)reason
- (NSString *) reason
{
return e_reason;
return e_reason;
}
- (NSDictionary *)userInfo
- (NSDictionary *) userInfo
{
return e_info;
return e_info;
}
- (Class) classForPortCoder
@ -140,49 +136,56 @@ _NSFoundationUncaughtExceptionHandler(NSException *exception)
return [self class];
}
- replacementObjectForPortCoder:(NSPortCoder*)aCoder
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder
{
return self;
return self;
}
- (void)encodeWithCoder: aCoder
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:e_name];
[aCoder encodeObject:e_reason];
[aCoder encodeObject:e_info];
[aCoder encodeValueOfObjCType: @encode(id) at: &e_name];
[aCoder encodeValueOfObjCType: @encode(id) at: &e_reason];
[aCoder encodeValueOfObjCType: @encode(id) at: &e_info];
}
- (id)initWithCoder: aDecoder
- (id) initWithCoder: (NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
e_name = [[aDecoder decodeObject] retain];
e_reason = [[aDecoder decodeObject] retain];
e_info = [[aDecoder decodeObject] retain];
return self;
[aDecoder decodeValueOfObjCType: @encode(id) at: &e_name];
[aDecoder decodeValueOfObjCType: @encode(id) at: &e_reason];
[aDecoder decodeValueOfObjCType: @encode(id) at: &e_info];
return self;
}
- deepen
- (id) deepen
{
e_name = [e_name copyWithZone:[self zone]];
e_reason = [e_reason copyWithZone:[self zone]];
e_info = [e_info copyWithZone:[self zone]];
return self;
e_name = [e_name copyWithZone: [self zone]];
e_reason = [e_reason copyWithZone: [self zone]];
e_info = [e_info copyWithZone: [self zone]];
return self;
}
- copyWithZone:(NSZone *)zone
- (id) copyWithZone: (NSZone *)zone
{
if (NSShouldRetainWithZone(self, zone))
return [self retain];
else
return [(NSException*)NSCopyObject(self, 0, zone) deepen];
if (NSShouldRetainWithZone(self, zone))
return RETAIN(self);
else
return [(NSException*)NSCopyObject(self, 0, zone) deepen];
}
- (NSString*) description
{
if (e_info)
return [NSString stringWithFormat: "%@ NAME:%@ REASON:%@ INFO:%@",
[super description], e_name, e_reason, e_info];
else
return [NSString stringWithFormat: "%@ NAME:%@ REASON:%@",
[super description], e_name, e_reason];
}
@end
void
void
_NSAddHandler( NSHandler *handler )
{
NSThread *thread;
@ -192,7 +195,7 @@ _NSAddHandler( NSHandler *handler )
thread->_exception_handler = handler;
}
void
void
_NSRemoveHandler( NSHandler *handler )
{
NSThread *thread;

View file

@ -1,4 +1,4 @@
/* Implementation of object for waiting on several input sources
/* Implementation of object for waiting on several input seurces
Copyright (C) 1996-1999 Free Software Foundation, Inc.
Original by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
@ -46,6 +46,8 @@
static int debug_run_loop = 0;
static NSDate *theFuture = nil;
static NSTimeInterval futureInterval;
static NSTimeInterval pastInterval;
@ -87,7 +89,7 @@ static SEL eventSel = @selector(receivedEvent:type:extra:forMode:);
@interface RunLoopWatcher: NSObject
{
@public
NSDate *_date; /* First to match layout of NSTimer */
NSTimeInterval _date; /* First to match layout of NSTimer */
BOOL _invalidated; /* 2nd to match layout of NSTimer */
IMP handleEvent; /* New-style event handling */
void *data;
@ -104,7 +106,6 @@ static SEL eventSel = @selector(receivedEvent:type:extra:forMode:);
- (void) dealloc
{
RELEASE(_date);
RELEASE(receiver);
[super dealloc];
}
@ -140,7 +141,7 @@ static SEL eventSel = @selector(receivedEvent:type:extra:forMode:);
* the NSTimer class is known to be the same as RunLoopWatcher for the
* first two elements.
*/
static inline NSDate* timerDate(NSTimer* timer)
static inline NSTimeInterval timerDate(NSTimer* timer)
{
return ((RunLoopWatcher*)timer)->_date;
}
@ -152,7 +153,12 @@ static inline BOOL timerInvalidated(NSTimer* timer)
static int aSort(RunLoopWatcher *i0, RunLoopWatcher *i1)
{
return [i0->_date compare: i1->_date];
if (i0->_date < i1->_date)
return -1;
else if (i0->_date > i1->_date)
return 1;
else
return 0;
}
@ -424,7 +430,7 @@ static int aSort(RunLoopWatcher *i0, RunLoopWatcher *i1)
{
NSDate *d = [obj limitDateForMode: mode];
ASSIGN(item->_date, d);
item->_date = [d timeIntervalSinceReferenceDate];
}
else if ([obj respondsToSelector: @selector(delegate)])
{
@ -433,13 +439,13 @@ static int aSort(RunLoopWatcher *i0, RunLoopWatcher *i1)
{
NSDate *d = [obj limitDateForMode: mode];
ASSIGN(item->_date, d);
item->_date = [d timeIntervalSinceReferenceDate];
}
else
ASSIGN(item->_date, theFuture);
item->_date = futureInterval;
}
else
ASSIGN(item->_date, theFuture);
item->_date = futureInterval;
FastArrayInsertSorted(watchers, (FastArrayItem)item, aSort);
}
@ -697,6 +703,8 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
{
[self currentRunLoop];
theFuture = RETAIN([NSDate distantFuture]);
futureInterval = [theFuture timeIntervalSinceReferenceDate];
pastInterval = [[NSDate distantPast] timeIntervalSinceReferenceDate];
#if GS_WITH_GC == 0
wRelImp = [[RunLoopWatcher class] instanceMethodForSelector: wRelSel];
wRetImp = [[RunLoopWatcher class] instanceMethodForSelector: wRetSel];
@ -736,12 +744,14 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
WatcherMapValueCallBacks, 0);
_wfdMap = NSCreateMapTable (NSIntMapKeyCallBacks,
WatcherMapValueCallBacks, 0);
_limit = RETAIN([NSDate date]);
return self;
}
- (void) dealloc
{
[self gcFinalize];
RELEASE(_limit);
RELEASE(_performers);
RELEASE(_timedPerformers);
[super dealloc];
@ -784,14 +794,14 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
/* Fire appropriate timers and determine the earliest time that anything
watched for becomes useless. */
- limitDateForMode: (NSString*)mode
- (NSDate*) limitDateForMode: (NSString*)mode
{
id saved_mode;
NSTimeInterval when;
FastArray timers;
FastArray watchers;
NSTimer *min_timer = nil;
RunLoopWatcher *min_watcher = nil;
FastArray watchers;
NSDate *when;
saved_mode = _current_mode;
_current_mode = mode;
@ -809,7 +819,7 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
continue;
}
if ([timerDate(min_timer) timeIntervalSinceNow] > 0)
if (timerDate(min_timer) > GSTimeNow())
{
break;
}
@ -819,12 +829,8 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
[min_timer fire];
if (timerInvalidated(min_timer) == NO)
{
unsigned index;
index = FastArrayInsertionPosition(timers,
FastArrayInsertSortedNoRetain(timers,
(FastArrayItem)min_timer, aSort);
FastArrayInsertItemNoRetain(timers,
(FastArrayItem)min_timer, index);
}
else
{
@ -851,8 +857,7 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
continue;
}
when = min_watcher->_date;
if ([when timeIntervalSinceNow] > 0)
if (min_watcher->_date > GSTimeNow())
{
break;
}
@ -887,18 +892,14 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
}
if (nxt && [nxt timeIntervalSinceNow] > 0.0)
{
unsigned index;
/*
* If the watcher has been given a revised limit date -
* re-insert it into the queue in the correct place.
*/
FastArrayRemoveItemAtIndexNoRelease(watchers, 0);
ASSIGN(min_watcher->_date, nxt);
index = FastArrayInsertionPosition(watchers,
(FastArrayItem)min_watcher, aSort);
FastArrayInsertItemNoRetain(watchers,
(FastArrayItem)min_watcher, index);
min_watcher->_date = [nxt timeIntervalSinceReferenceDate];
FastArrayInsertSortedNoRetain(watchers,
(FastArrayItem)min_watcher, aSort);
}
else
{
@ -915,47 +916,38 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
}
}
/*
* If there are timers - set limit date to the earliest of them.
*/
if (min_timer)
{
when = [min_timer fireDate];
}
else
{
when = nil;
}
_current_mode = saved_mode;
/*
* If there are timers - set limit date to the earliest of them.
* If there are watchers, set the limit date to that of the earliest
* watcher (or leave it as the date of the earliest timer if that is
* before the watchers limit).
*/
if (min_watcher)
if (min_timer)
{
if (when == nil)
when = timerDate(min_timer);
if (min_watcher && min_watcher->_date < when)
{
when = min_watcher->_date;
}
else
{
when = [when earlierDate: min_watcher->_date];
}
}
/*
* 'when' will only be nil if there are neither timers nor watchers
* outstanding.
*/
if (when && debug_run_loop)
else if (min_watcher)
{
printf ("\tNSRunLoop limit date %f\n",
[when timeIntervalSinceReferenceDate]);
when = min_watcher->_date;
}
else
{
return nil; /* Nothing waiting to be done. */
}
_current_mode = saved_mode;
return when;
if (debug_run_loop)
{
printf ("\tNSRunLoop limit date %f\n", when);
}
_limit = [_limit initWithTimeIntervalSinceReferenceDate: when];
return _limit;
}
- (RunLoopWatcher*) _getWatcher: (void*)data
@ -1059,14 +1051,6 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
printf ("\tNSRunLoop accept input before %f (seconds from now %f)\n",
[limit_date timeIntervalSinceReferenceDate], ti);
/* If LIMIT_DATE has already past, return immediately. */
if (ti < 0)
{
[self _checkPerformers];
if (debug_run_loop)
printf ("\tNSRunLoop limit date past, returning\n");
_current_mode = saved_mode;
return;
}
timeout.tv_sec = ti;
timeout.tv_usec = (ti - timeout.tv_sec) * 1000000.0;
select_timeout = &timeout;
@ -1075,6 +1059,9 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
{
/* The LIMIT_DATE has already past; return immediately without
polling any inputs. */
[self _checkPerformers];
if (debug_run_loop)
printf ("\tNSRunLoop limit date past, returning\n");
_current_mode = saved_mode;
return;
}
@ -1305,12 +1292,20 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
}
/* Use the earlier of the two dates we have. */
d = RETAIN([d earlierDate: date]);
d = [d earlierDate: date];
/*
* If the date is not our own ivar, we must retain it so it doesn't
* get destroyed inside the run loop
*/
if (d != _limit)
RETAIN(d);
/* Wait, listening to our input sources. */
[self acceptInputForMode: mode beforeDate: d];
RELEASE(d);
if (d != _limit)
RELEASE(d);
return YES;
}

View file

@ -26,22 +26,10 @@
#include <Foundation/NSThread.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSString.h>
#include <base/o_map.h>
#include <base/NotificationDispatcher.h>
#include <Foundation/NSNotificationQueue.h>
// Class variables
#define USING_THREAD_COLLECTION 0
#if USING_THREAD_COLLECTION
/* For managing the collection of all NSThread objects. Note, however,
threads that have not yet called +currentThread will not be in the
collection.
xxx Do we really need this collection anyway?
How about getting rid of it? */
static NSRecursiveLock *thread_lock;
static o_map_t thread_id_2_nsthread;
#endif
/* Flag indicating whether the objc runtime ever went multi-threaded. */
static BOOL entered_multi_threaded_state;
@ -86,7 +74,7 @@ void gnustep_base_thread_callback()
if (!entered_multi_threaded_state)
{
entered_multi_threaded_state = YES;
[NotificationDispatcher
[[NSNotificationCenter defaultCenter]
postNotificationName: NSBecomingMultiThreaded
object: nil];
}
@ -100,11 +88,6 @@ void gnustep_base_thread_callback()
{
if (self == [NSThread class])
{
#if USING_THREAD_COLLECTION
thread_id_2_nsthread = o_map_of_non_owned_void_p ();
thread_lock = [[[NSRecursiveLock alloc] init]
autorelease];
#endif
entered_multi_threaded_state = NO;
objc_set_thread_callback(gnustep_base_thread_callback);
}
@ -115,14 +98,12 @@ void gnustep_base_thread_callback()
- (void)dealloc
{
[_thread_dictionary release];
TEST_RELEASE(_thread_dictionary);
[super dealloc];
}
- init
- (id) init
{
[super init];
/* Make it easy and fast to get this NSThread object from the thread. */
objc_thread_set_data (self);
@ -131,15 +112,6 @@ void gnustep_base_thread_callback()
_exception_handler = NULL;
init_autorelease_thread_vars (&_autorelease_vars);
#if USING_THREAD_COLLECTION
/* Register ourselves in the maptable of all threads. */
// Lock the thread list so it doesn't change on us
[thread_lock lock];
// Save the thread in our thread map; NOTE: this will not retain it
o_map_at_key_put_value_known_absent (thread_id_2_nsthread, tid, t);
[thread_lock unlock];
#endif
return self;
}
@ -228,29 +200,19 @@ void gnustep_base_thread_callback()
NSThread *t;
// the current NSThread
t = [NSThread currentThread];
t = GSCurrentThread();
// Post the notification
[NotificationDispatcher
[[NSNotificationCenter defaultCenter]
postNotificationName: NSThreadExiting
object: t];
#if USING_THREAD_COLLECTION
{
_objc_thread_t tid;
// Get current thread id from runtime
tid = objc_thread_id();
// Lock the thread list so it doesn't change on us
[thread_lock lock];
// Remove the thread from the map
o_map_remove_key (thread_id_2_nsthread, tid);
// Unlock the thread list
[thread_lock unlock];
}
#endif
/*
* Release anything in our autorelease pools
*/
[NSAutoreleasePool _endThread];
// Release the thread object
[t release];
RELEASE(t);
// xxx Clean up any outstanding NSAutoreleasePools here.

View file

@ -38,7 +38,7 @@
repeats: (BOOL)f
{
_interval = seconds;
_date = [[NSDate alloc] initWithTimeIntervalSinceNow: seconds];
_date = GSTimeNow() + seconds;
_target = t;
_selector = sel;
_info = info;
@ -46,12 +46,6 @@
return self;
}
- (void) dealloc
{
RELEASE(_date);
[super dealloc];
}
+ timerWithTimeInterval: (NSTimeInterval)ti
invocation: invocation
repeats: (BOOL)f
@ -114,25 +108,18 @@
[self invalidate];
else if (!_invalidated)
{
NSTimeInterval ti = [_date timeIntervalSinceReferenceDate];
NSTimeInterval now = GSTimeNow();
int inc = -1;
NSAssert(now < 0.0, NSInternalInconsistencyException);
while (ti <= now) // xxx remove this
while (_date <= now) // xxx remove this
{
inc++;
ti += _interval;
_date += _interval;
}
#ifdef LOG_MISSED
if (inc > 0)
NSLog(@"Missed %d timeouts at %f second intervals", inc, _interval);
#endif
/*
* Rely on feature of NSDate implementation that it's possible to
* re-initialize a date!
*/
_date = [_date initWithTimeIntervalSinceReferenceDate: ti];
}
}
@ -149,7 +136,7 @@
- fireDate
{
return _date;
return [NSDate dateWithTimeIntervalSinceReferenceDate: _date];
}
- userInfo
@ -157,8 +144,13 @@
return _info;
}
- (int)compare:(NSTimer*)anotherTimer
- (int) compare: (NSTimer*)anotherTimer
{
return [_date compare: anotherTimer->_date];
if (_date < anotherTimer->_date)
return NSOrderedAscending;
else if (_date > anotherTimer->_date)
return NSOrderedDescending;
else
return NSOrderedSame;
}
@end