mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
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:
parent
4b1b047b85
commit
bad4f54d67
14 changed files with 302 additions and 255 deletions
16
ChangeLog
16
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -42,6 +42,7 @@ extern id NSDefaultRunLoopMode;
|
|||
NSMutableArray *_timedPerformers;
|
||||
NSMapTable *_rfdMap;
|
||||
NSMapTable *_wfdMap;
|
||||
NSDate *_limit;
|
||||
}
|
||||
|
||||
+ (NSRunLoop*) currentRunLoop;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue