summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-07-06 16:56:09 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-07-06 16:56:09 +0200
commit22f6836925cb1c682045497d214773a3d04e60b2 (patch)
treeb40f86ec170b3b2ddfda901df440b88fd4d253e9
parent6f2c4e98c734221010b3d4049ba826775d87a5fc (diff)
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.
-rw-r--r--Timer.st35
1 files changed, 15 insertions, 20 deletions
diff --git a/Timer.st b/Timer.st
index 438d2de..a5d3e93 100644
--- a/Timer.st
+++ b/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.
- ].
- ].
+ ]].
+ ]
]
]