mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Fix for mutation of timers array during firing of a timer.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25706 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
357314fb8e
commit
b0aed5aebb
2 changed files with 44 additions and 10 deletions
|
@ -1,3 +1,8 @@
|
|||
2007-12-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSRunLoop.m: Deal with mutation of timers array during
|
||||
firing of a timer.
|
||||
|
||||
2007-12-07 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/Additions/GNUstepBase/GSConfig.h.in:
|
||||
|
|
|
@ -860,26 +860,55 @@ static inline BOOL timerInvalidated(NSTimer *t)
|
|||
d = timerDate(t);
|
||||
if ([d timeIntervalSinceReferenceDate] > now)
|
||||
{
|
||||
when = [timerDate(t) copy];
|
||||
when = [d copy];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Firing will also increment its fireDate, if it is repeating. */
|
||||
/* When firing the timer we must remove it from
|
||||
* the loop so that if the -fire methods re-runs
|
||||
* the loop we do not get recursive entry into
|
||||
* the timer. This appears to be the behavior
|
||||
* in MacOS-X also.
|
||||
*/
|
||||
GSIArrayRemoveItemAtIndexNoRelease(timers, i);
|
||||
[t fire];
|
||||
GSPrivateNotifyASAP(); /* Post notifications. */
|
||||
IF_NO_GC([arp emptyPool]);
|
||||
now = GSTimeNow();
|
||||
|
||||
/* Increment fire date unless timer is invalidated or the
|
||||
* timeout handler has already updated it.
|
||||
/* The -fire method could have re-run the current run loop
|
||||
* and caused timers to have been added (not a problem),
|
||||
* or invalidated and/or removed. In the latter case the
|
||||
* timers array could have shrunk, so we must check that
|
||||
* our loop index is not too large.
|
||||
*/
|
||||
if (timerInvalidated(t) == NO && timerDate(t) == d)
|
||||
if (i > GSIArrayCount(timers))
|
||||
{
|
||||
d = [[NSDate alloc]
|
||||
initWithTimeIntervalSinceReferenceDate:
|
||||
now + [t timeInterval]];
|
||||
[t setFireDate: d];
|
||||
RELEASE(d);
|
||||
i = GSIArrayCount(timers);
|
||||
}
|
||||
if (timerInvalidated(t) == NO)
|
||||
{
|
||||
/* Increment fire date unless the timeout handler
|
||||
* has already updated it. Then put the timer back
|
||||
* in the array so that it can fire again next
|
||||
* time this method is called.
|
||||
*/
|
||||
if (timerDate(t) == d)
|
||||
{
|
||||
d = [[NSDate alloc]
|
||||
initWithTimeIntervalSinceReferenceDate:
|
||||
now + [t timeInterval]];
|
||||
[t setFireDate: d];
|
||||
RELEASE(d);
|
||||
}
|
||||
GSIArrayInsertItemNoRetain(timers, (GSIArrayItem)((id)t), i);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The timer was invalidated, so we can release it as we
|
||||
* aren't p[utting it back in the array.
|
||||
*/
|
||||
RELEASE(t);
|
||||
}
|
||||
}
|
||||
_currentMode = savedMode;
|
||||
|
|
Loading…
Reference in a new issue