timer: Try to avoid copying the entire timerlist all the timer
Make sure that we only remove from one process, this way we can check if the list is empty without having a lock. The list is sorted so even if we get interrupted between the [condition] whileFalse: [res] and someone adds an older timer, it is okay to use this timer.
This commit is contained in:
parent
6f2c4e98c7
commit
22f6836925
35
Timer.st
35
Timer.st
|
@ -56,7 +56,13 @@ Object subclass: Timer [
|
|||
|
||||
cancel [
|
||||
<category: 'management'>
|
||||
schedule removeTimer: self.
|
||||
"Remember that the timer is gone."
|
||||
schedule := nil.
|
||||
]
|
||||
|
||||
isCanceled [
|
||||
<category: 'management'>
|
||||
^ schedule == nil.
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -111,13 +117,6 @@ bit difficult to do this race free.'>
|
|||
^ sched
|
||||
]
|
||||
|
||||
removeTimer: aSched [
|
||||
<category: 'schedule'>
|
||||
sem critical: [
|
||||
queue remove: aSched ifAbsent: [].
|
||||
].
|
||||
]
|
||||
|
||||
runTimers [
|
||||
<category: 'delay_loop'>
|
||||
|
||||
|
@ -131,24 +130,20 @@ bit difficult to do this race free.'>
|
|||
|
||||
fireTimers: now [
|
||||
<category: 'private'>
|
||||
| copy |
|
||||
|
||||
"Create a shallow copy of the data"
|
||||
copy := sem critical: [queue copy].
|
||||
|
||||
"Now execute the timers. One way or another this is crazy. If we have
|
||||
a long blocking application or a deadlock the timer queue will get
|
||||
stuck. But if we run this in a new process a later process might be run
|
||||
before this process, changing the order of the timers."
|
||||
copy do: [:each |
|
||||
each timeout > now ifTrue: [^true].
|
||||
sem critical: [queue remove: each].
|
||||
[
|
||||
each fire
|
||||
] on: Error do: [:e |
|
||||
"Only this process will remove items, this is why we can check isEmpty
|
||||
without having the lock"
|
||||
[queue isEmpty or: [queue first timeout > now]] whileFalse: [ | each |
|
||||
each := sem critical: [queue removeFirst].
|
||||
each isCanceled ifFalse: [
|
||||
[each fire] on: Error do: [:e |
|
||||
e logException: 'Execution of timer failed: %1' % {e tag} area: #timer.
|
||||
].
|
||||
].
|
||||
]].
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
|
Reference in New Issue