mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +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
c04361b3d6
commit
33691693fa
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>
|
2007-12-07 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Headers/Additions/GNUstepBase/GSConfig.h.in:
|
* Headers/Additions/GNUstepBase/GSConfig.h.in:
|
||||||
|
|
|
@ -860,26 +860,55 @@ static inline BOOL timerInvalidated(NSTimer *t)
|
||||||
d = timerDate(t);
|
d = timerDate(t);
|
||||||
if ([d timeIntervalSinceReferenceDate] > now)
|
if ([d timeIntervalSinceReferenceDate] > now)
|
||||||
{
|
{
|
||||||
when = [timerDate(t) copy];
|
when = [d copy];
|
||||||
break;
|
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];
|
[t fire];
|
||||||
GSPrivateNotifyASAP(); /* Post notifications. */
|
GSPrivateNotifyASAP(); /* Post notifications. */
|
||||||
IF_NO_GC([arp emptyPool]);
|
IF_NO_GC([arp emptyPool]);
|
||||||
now = GSTimeNow();
|
now = GSTimeNow();
|
||||||
|
|
||||||
/* Increment fire date unless timer is invalidated or the
|
/* The -fire method could have re-run the current run loop
|
||||||
* timeout handler has already updated it.
|
* 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]
|
i = GSIArrayCount(timers);
|
||||||
initWithTimeIntervalSinceReferenceDate:
|
}
|
||||||
now + [t timeInterval]];
|
if (timerInvalidated(t) == NO)
|
||||||
[t setFireDate: d];
|
{
|
||||||
RELEASE(d);
|
/* 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;
|
_currentMode = savedMode;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue