mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
make timers more robust
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28656 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
b510b0d659
commit
4f13b89771
3 changed files with 67 additions and 18 deletions
|
@ -5,7 +5,11 @@
|
||||||
method to only fire one timer (excluding the private housekeeping one).
|
method to only fire one timer (excluding the private housekeeping one).
|
||||||
Changing to only fire one timer actually allows the code to be simpler
|
Changing to only fire one timer actually allows the code to be simpler
|
||||||
so it's a good update in its own right, not just a OSX compatibility
|
so it's a good update in its own right, not just a OSX compatibility
|
||||||
tweak.
|
tweak. I also made incrementing repeated timers a bit more robust,
|
||||||
|
checking that they provide a valid increment time interval and
|
||||||
|
removing them from the loop if they don't.
|
||||||
|
* Source/NSTimer.m: slightly tidy/clarify initialisation code and
|
||||||
|
documentation.
|
||||||
|
|
||||||
2009-09-08 Richard Frith-Macdonald <rfm@gnu.org>
|
2009-09-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <math.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h> /* for memset() */
|
#include <string.h> /* for memset() */
|
||||||
|
@ -813,6 +814,20 @@ static inline BOOL timerInvalidated(NSTimer *t)
|
||||||
GSIArray timers;
|
GSIArray timers;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
if ([timer isKindOfClass: [NSTimer class]] == NO
|
||||||
|
|| [timer isProxy] == YES)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"[%@-%@] not a valid timer",
|
||||||
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
||||||
|
}
|
||||||
|
if ([mode isKindOfClass: [NSString class]] == NO)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"[%@-%@] not a valid mode",
|
||||||
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
||||||
|
}
|
||||||
|
|
||||||
NSDebugMLLog(@"NSRunLoop", @"add timer for %f in %@",
|
NSDebugMLLog(@"NSRunLoop", @"add timer for %f in %@",
|
||||||
[[timer fireDate] timeIntervalSinceReferenceDate], mode);
|
[[timer fireDate] timeIntervalSinceReferenceDate], mode);
|
||||||
|
|
||||||
|
@ -875,10 +890,38 @@ updateTimer(NSTimer *t, NSDate *d, NSTimeInterval now)
|
||||||
NSTimeInterval ti = [d timeIntervalSinceReferenceDate];
|
NSTimeInterval ti = [d timeIntervalSinceReferenceDate];
|
||||||
NSTimeInterval increment = [t timeInterval];
|
NSTimeInterval increment = [t timeInterval];
|
||||||
|
|
||||||
ti += increment;
|
if (increment <= 0.0)
|
||||||
while (ti < now)
|
|
||||||
{
|
{
|
||||||
ti += increment;
|
/* Should never get here ... unless a subclass is returning
|
||||||
|
* a bad interval ... we return NO so that the timer gets
|
||||||
|
* removed from the loop.
|
||||||
|
*/
|
||||||
|
NSLog(@"WARNING timer %@ had bad interval ... removed", t);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ti += increment; // Hopefully a single increment will do.
|
||||||
|
|
||||||
|
if (ti < now)
|
||||||
|
{
|
||||||
|
NSTimeInterval add;
|
||||||
|
|
||||||
|
/* Just incrementing the date was insufficieint to bring it to
|
||||||
|
* the current time, so we must have missed one or more fire
|
||||||
|
* opportunities, or the fire date has been set on the timer.
|
||||||
|
* If a fire date long ago has been set and the increment value
|
||||||
|
* is really small, we might need to increment very many times
|
||||||
|
* to get the new fire date. To avoid looping for ages, we
|
||||||
|
* calculate the number of increments needed and do them in one
|
||||||
|
* go.
|
||||||
|
*/
|
||||||
|
add = floor((now - ti) / increment);
|
||||||
|
ti += (increment * add);
|
||||||
|
if (ti < now)
|
||||||
|
{
|
||||||
|
add++;
|
||||||
|
ti += increment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
d = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: ti];
|
d = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: ti];
|
||||||
[t setFireDate: d];
|
[t setFireDate: d];
|
||||||
|
|
|
@ -69,22 +69,21 @@ static Class NSDate_class;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** <init />
|
||||||
* <init />
|
|
||||||
* Initialise the receive, a newly allocated NSTimer object.<br />
|
* Initialise the receive, a newly allocated NSTimer object.<br />
|
||||||
* The fd argument specifies an initial fire date ... if it is not
|
|
||||||
* supplied (a nil object) then the ti argument is used to create
|
|
||||||
* a start date relative to the current time.<br />
|
|
||||||
* The ti argument specifies the time (in seconds) between the firing.
|
* The ti argument specifies the time (in seconds) between the firing.
|
||||||
* If it is less than or equal to 0.0 then a small interval is chosen
|
* If it is less than or equal to 0.0 then a small interval is chosen
|
||||||
* automatically.<br />
|
* automatically.<br />
|
||||||
|
* The fd argument specifies an initial fire date copied by the timer...
|
||||||
|
* if it is not supplied (a nil object) then the ti argument is used to
|
||||||
|
* create a start date relative to the current time.<br />
|
||||||
* The f argument specifies whether the timer will fire repeatedly
|
* The f argument specifies whether the timer will fire repeatedly
|
||||||
* or just once.<br />
|
* or just once.<br />
|
||||||
* If the selector argument is zero, then then object is an invocation
|
* If the selector argument is zero, then then object is an invocation
|
||||||
* to be used when the timer fires. otherwise, the object is sent the
|
* to be used when the timer fires. otherwise, the object is sent the
|
||||||
* message specified by the selector and with the timer as an argument.<br />
|
* message specified by the selector and with the timer as an argument.<br />
|
||||||
* The fd, object and info arguments will be retained until the timer is
|
* The object and info arguments will be retained until the timer is
|
||||||
* invalidated.<br />
|
* invalidated.
|
||||||
*/
|
*/
|
||||||
- (id) initWithFireDate: (NSDate*)fd
|
- (id) initWithFireDate: (NSDate*)fd
|
||||||
interval: (NSTimeInterval)ti
|
interval: (NSTimeInterval)ti
|
||||||
|
@ -93,26 +92,30 @@ static Class NSDate_class;
|
||||||
userInfo: (id)info
|
userInfo: (id)info
|
||||||
repeats: (BOOL)f
|
repeats: (BOOL)f
|
||||||
{
|
{
|
||||||
if (ti <= 0)
|
if (ti <= 0.0)
|
||||||
{
|
{
|
||||||
ti = 0.0001;
|
ti = 0.0001;
|
||||||
}
|
}
|
||||||
_interval = ti;
|
|
||||||
if (fd == nil)
|
if (fd == nil)
|
||||||
{
|
{
|
||||||
_date = [[NSDate_class allocWithZone: NSDefaultMallocZone()]
|
_date = [[NSDate_class allocWithZone: NSDefaultMallocZone()]
|
||||||
initWithTimeIntervalSinceNow: _interval];
|
initWithTimeIntervalSinceNow: ti];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_date = [fd copy];
|
_date = [fd copyWithZone: NSDefaultMallocZone()];
|
||||||
}
|
}
|
||||||
_target = RETAIN(object);
|
_target = RETAIN(object);
|
||||||
_selector = selector;
|
_selector = selector;
|
||||||
_info = RETAIN(info);
|
_info = RETAIN(info);
|
||||||
_repeats = f;
|
if (f == YES)
|
||||||
if (_repeats == NO)
|
|
||||||
{
|
{
|
||||||
|
_repeats = YES;
|
||||||
|
_interval = ti;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_repeats = NO;
|
||||||
_interval = 0.0;
|
_interval = 0.0;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
@ -266,7 +269,6 @@ static Class NSDate_class;
|
||||||
- (void) invalidate
|
- (void) invalidate
|
||||||
{
|
{
|
||||||
/* OPENSTEP allows this method to be called multiple times. */
|
/* OPENSTEP allows this method to be called multiple times. */
|
||||||
//NSAssert(_invalidated == NO, NSInternalInconsistencyException);
|
|
||||||
_invalidated = YES;
|
_invalidated = YES;
|
||||||
if (_target != nil)
|
if (_target != nil)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue