aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2008-04-03 03:43:18 +0000
committerStefan Monnier2008-04-03 03:43:18 +0000
commite0f0f3efb4fdedbb040968eba953d433816585bc (patch)
tree21b02491488b739dd577dd2002dc618bee0639d1
parent7662e6afa351b7d8747c5f039045ab429594e7cd (diff)
downloademacs-e0f0f3efb4fdedbb040968eba953d433816585bc.tar.gz
emacs-e0f0f3efb4fdedbb040968eba953d433816585bc.zip
(timer): Define as a defstruct, so we can name the fields, to make the
code clearer. Rewrite all `aset' and `aref' using the defined accessors. (timer--time): New pseudo-field. (timer-set-time, timer-set-idle-time, timer-inc-time) (timer-set-time-with-usecs, with-timeout-suspend): Use it. (timer--time-less-p): New function. (timer--activate): New function, extracted from timer-activate. (timer-activate-when-idle, timer-activate): Use it. (cancel-function-timers): Use dolist.
-rw-r--r--lisp/ChangeLog17
-rw-r--r--lisp/emacs-lisp/timer.el212
2 files changed, 109 insertions, 120 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 368f6034854..d7ef6135529 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,7 +1,20 @@
12008-04-03 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * emacs-lisp/timer.el (timer): Define as a defstruct, so we can
4 name the fields, to make the code clearer.
5 Rewrite all `aset' and `aref' using the defined accessors.
6 (timer--time): New pseudo-field.
7 (timer-set-time, timer-set-idle-time, timer-inc-time)
8 (timer-set-time-with-usecs, with-timeout-suspend): Use it.
9 (timer--time-less-p): New function.
10 (timer--activate): New function, extracted from timer-activate.
11 (timer-activate-when-idle, timer-activate): Use it.
12 (cancel-function-timers): Use dolist.
13
12008-04-03 Glenn Morris <rgm@gnu.org> 142008-04-03 Glenn Morris <rgm@gnu.org>
2 15
3 * add-log.el (c-beginning-of-defun, c-end-of-defun): Remove 16 * add-log.el (c-beginning-of-defun, c-end-of-defun):
4 declarations; no longer used. 17 Remove declarations; no longer used.
5 (c-cpp-define-name, c-defun-name): Declare as functions. 18 (c-cpp-define-name, c-defun-name): Declare as functions.
6 19
7 * calendar/diary-lib.el (diary-mail-addr): Use bound-and-true-p. 20 * calendar/diary-lib.el (diary-mail-addr): Use bound-and-true-p.
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 6ca68824d95..36f3a0ecf9a 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -35,29 +35,45 @@
35;; triggered-p is nil if the timer is active (waiting to be triggered), 35;; triggered-p is nil if the timer is active (waiting to be triggered),
36;; t if it is inactive ("already triggered", in theory) 36;; t if it is inactive ("already triggered", in theory)
37 37
38(defun timer-create () 38(eval-when-compile (require 'cl))
39 "Create a timer object which can be passed to `timer-activate'." 39
40 (let ((timer (make-vector 8 nil))) 40(defstruct (timer
41 (aset timer 0 t) 41 (:constructor nil)
42 timer)) 42 (:copier nil)
43 (:constructor timer-create ())
44 (:type vector)
45 (:conc-name timer--))
46 (triggered t)
47 high-seconds low-seconds usecs repeat-delay function args idle-delay)
43 48
44(defun timerp (object) 49(defun timerp (object)
45 "Return t if OBJECT is a timer." 50 "Return t if OBJECT is a timer."
46 (and (vectorp object) (= (length object) 8))) 51 (and (vectorp object) (= (length object) 8)))
47 52
53;; Pseudo field `time'.
54(defun timer--time (timer)
55 (list (timer--high-seconds timer)
56 (timer--low-seconds timer)
57 (timer--usecs timer)))
58
59(defsetf timer--time
60 (lambda (timer time)
61 (or (timerp timer) (error "Invalid timer"))
62 (setf (timer--high-seconds timer) (pop time))
63 (setf (timer--low-seconds timer)
64 (if (consp time) (car time) time))
65 (setf (timer--usecs timer) (or (and (consp time) (consp (cdr time))
66 (cadr time))
67 0))))
68
69
48(defun timer-set-time (timer time &optional delta) 70(defun timer-set-time (timer time &optional delta)
49 "Set the trigger time of TIMER to TIME. 71 "Set the trigger time of TIMER to TIME.
50TIME must be in the internal format returned by, e.g., `current-time'. 72TIME must be in the internal format returned by, e.g., `current-time'.
51If optional third argument DELTA is a positive number, make the timer 73If optional third argument DELTA is a positive number, make the timer
52fire repeatedly that many seconds apart." 74fire repeatedly that many seconds apart."
53 (or (timerp timer) 75 (setf (timer--time timer) time)
54 (error "Invalid timer")) 76 (setf (timer--repeat-delay timer) (and (numberp delta) (> delta 0) delta))
55 (aset timer 1 (car time))
56 (aset timer 2 (if (consp (cdr time)) (car (cdr time)) (cdr time)))
57 (aset timer 3 (or (and (consp (cdr time)) (consp (cdr (cdr time)))
58 (nth 2 time))
59 0))
60 (aset timer 4 (and (numberp delta) (> delta 0) delta))
61 timer) 77 timer)
62 78
63(defun timer-set-idle-time (timer secs &optional repeat) 79(defun timer-set-idle-time (timer secs &optional repeat)
@@ -66,19 +82,11 @@ SECS may be an integer, floating point number, or the internal
66time format (HIGH LOW USECS) returned by, e.g., `current-idle-time'. 82time format (HIGH LOW USECS) returned by, e.g., `current-idle-time'.
67If optional third argument REPEAT is non-nil, make the timer 83If optional third argument REPEAT is non-nil, make the timer
68fire each time Emacs is idle for that many seconds." 84fire each time Emacs is idle for that many seconds."
69 (or (timerp timer)
70 (error "Invalid timer"))
71 (if (consp secs) 85 (if (consp secs)
72 (progn (aset timer 1 (car secs)) 86 (setf (timer--time timer) secs)
73 (aset timer 2 (if (consp (cdr secs)) (car (cdr secs)) (cdr secs))) 87 (setf (timer--time timer) '(0 0 0))
74 (aset timer 3 (or (and (consp (cdr secs)) (consp (cdr (cdr secs)))
75 (nth 2 secs))
76 0)))
77 (aset timer 1 0)
78 (aset timer 2 0)
79 (aset timer 3 0)
80 (timer-inc-time timer secs)) 88 (timer-inc-time timer secs))
81 (aset timer 4 repeat) 89 (setf (timer--repeat-delay timer) repeat)
82 timer) 90 timer)
83 91
84(defun timer-next-integral-multiple-of-time (time secs) 92(defun timer-next-integral-multiple-of-time (time secs)
@@ -115,6 +123,7 @@ of SECS seconds since the epoch. SECS may be a fraction."
115(defun timer-relative-time (time secs &optional usecs) 123(defun timer-relative-time (time secs &optional usecs)
116 "Advance TIME by SECS seconds and optionally USECS microseconds. 124 "Advance TIME by SECS seconds and optionally USECS microseconds.
117SECS may be either an integer or a floating point number." 125SECS may be either an integer or a floating point number."
126 ;; FIXME: we should just use (time-add time (list 0 secs usecs))
118 (let ((high (car time)) 127 (let ((high (car time))
119 (low (if (consp (cdr time)) (nth 1 time) (cdr time))) 128 (low (if (consp (cdr time)) (nth 1 time) (cdr time)))
120 (micro (if (numberp (car-safe (cdr-safe (cdr time)))) 129 (micro (if (numberp (car-safe (cdr-safe (cdr time))))
@@ -136,16 +145,22 @@ SECS may be either an integer or a floating point number."
136 145
137 (list high low (and (/= micro 0) micro)))) 146 (list high low (and (/= micro 0) micro))))
138 147
148(defun timer--time-less-p (t1 t2)
149 "Say whether time value T1 is less than time value T2."
150 ;; FIXME just use time-less-p.
151 (destructuring-bind (high1 low1 micro1) (timer--time t1)
152 (destructuring-bind (high2 low2 micro2) (timer--time t2)
153 (or (< high1 high2)
154 (and (= high1 high2)
155 (or (< low1 low2)
156 (and (= low1 low2)
157 (< micro1 micro2))))))))
158
139(defun timer-inc-time (timer secs &optional usecs) 159(defun timer-inc-time (timer secs &optional usecs)
140 "Increment the time set in TIMER by SECS seconds and USECS microseconds. 160 "Increment the time set in TIMER by SECS seconds and USECS microseconds.
141SECS may be a fraction. If USECS is omitted, that means it is zero." 161SECS may be a fraction. If USECS is omitted, that means it is zero."
142 (let ((time (timer-relative-time 162 (setf (timer--time timer)
143 (list (aref timer 1) (aref timer 2) (aref timer 3)) 163 (timer-relative-time (timer--time timer) secs usecs)))
144 secs
145 usecs)))
146 (aset timer 1 (nth 0 time))
147 (aset timer 2 (nth 1 time))
148 (aset timer 3 (or (nth 2 time) 0))))
149 164
150(defun timer-set-time-with-usecs (timer time usecs &optional delta) 165(defun timer-set-time-with-usecs (timer time usecs &optional delta)
151 "Set the trigger time of TIMER to TIME plus USECS. 166 "Set the trigger time of TIMER to TIME plus USECS.
@@ -153,12 +168,9 @@ TIME must be in the internal format returned by, e.g., `current-time'.
153The microsecond count from TIME is ignored, and USECS is used instead. 168The microsecond count from TIME is ignored, and USECS is used instead.
154If optional fourth argument DELTA is a positive number, make the timer 169If optional fourth argument DELTA is a positive number, make the timer
155fire repeatedly that many seconds apart." 170fire repeatedly that many seconds apart."
156 (or (timerp timer) 171 (setf (timer--time timer) time)
157 (error "Invalid timer")) 172 (setf (timer--usecs timer) usecs)
158 (aset timer 1 (nth 0 time)) 173 (setf (timer--repeat-delay timer) (and (numberp delta) (> delta 0) delta))
159 (aset timer 2 (nth 1 time))
160 (aset timer 3 usecs)
161 (aset timer 4 (and (numberp delta) (> delta 0) delta))
162 timer) 174 timer)
163(make-obsolete 'timer-set-time-with-usecs 175(make-obsolete 'timer-set-time-with-usecs
164 "use `timer-set-time' and `timer-inc-time' instead." 176 "use `timer-set-time' and `timer-inc-time' instead."
@@ -168,34 +180,20 @@ fire repeatedly that many seconds apart."
168 "Make TIMER call FUNCTION with optional ARGS when triggering." 180 "Make TIMER call FUNCTION with optional ARGS when triggering."
169 (or (timerp timer) 181 (or (timerp timer)
170 (error "Invalid timer")) 182 (error "Invalid timer"))
171 (aset timer 5 function) 183 (setf (timer--function timer) function)
172 (aset timer 6 args) 184 (setf (timer--args timer) args)
173 timer) 185 timer)
174 186
175(defun timer-activate (timer &optional triggered-p reuse-cell) 187(defun timer--activate (timer &optional triggered-p reuse-cell idle)
176 "Put TIMER on the list of active timers.
177
178If TRIGGERED-P is t, that means to make the timer inactive
179\(put it on the list, but mark it as already triggered).
180To remove from the list, use `cancel-timer'.
181
182REUSE-CELL, if non-nil, is a cons cell to reuse instead
183of allocating a new one."
184 (if (and (timerp timer) 188 (if (and (timerp timer)
185 (integerp (aref timer 1)) 189 (integerp (timer--high-seconds timer))
186 (integerp (aref timer 2)) 190 (integerp (timer--low-seconds timer))
187 (integerp (aref timer 3)) 191 (integerp (timer--usecs timer))
188 (aref timer 5)) 192 (timer--function timer))
189 (let ((timers timer-list) 193 (let ((timers (if idle timer-idle-list timer-list))
190 last) 194 last)
191 ;; Skip all timers to trigger before the new one. 195 ;; Skip all timers to trigger before the new one.
192 (while (and timers 196 (while (and timers (timer--time-less-p (car timers) timer))
193 (or (> (aref timer 1) (aref (car timers) 1))
194 (and (= (aref timer 1) (aref (car timers) 1))
195 (> (aref timer 2) (aref (car timers) 2)))
196 (and (= (aref timer 1) (aref (car timers) 1))
197 (= (aref timer 2) (aref (car timers) 2))
198 (> (aref timer 3) (aref (car timers) 3)))))
199 (setq last timers 197 (setq last timers
200 timers (cdr timers))) 198 timers (cdr timers)))
201 (if reuse-cell 199 (if reuse-cell
@@ -206,12 +204,25 @@ of allocating a new one."
206 ;; Insert new timer after last which possibly means in front of queue. 204 ;; Insert new timer after last which possibly means in front of queue.
207 (if last 205 (if last
208 (setcdr last reuse-cell) 206 (setcdr last reuse-cell)
209 (setq timer-list reuse-cell)) 207 (if idle
210 (aset timer 0 triggered-p) 208 (setq timer-idle-list reuse-cell)
211 (aset timer 7 nil) 209 (setq timer-list reuse-cell)))
210 (setf (timer--triggered timer) triggered-p)
211 (setf (timer--idle-delay timer) idle)
212 nil) 212 nil)
213 (error "Invalid or uninitialized timer"))) 213 (error "Invalid or uninitialized timer")))
214 214
215(defun timer-activate (timer &optional triggered-p reuse-cell idle)
216 "Put TIMER on the list of active timers.
217
218If TRIGGERED-P is t, that means to make the timer inactive
219\(put it on the list, but mark it as already triggered).
220To remove from the list, use `cancel-timer'.
221
222REUSE-CELL, if non-nil, is a cons cell to reuse instead
223of allocating a new one."
224 (timer--activate timer triggered-p reuse-cell nil))
225
215(defun timer-activate-when-idle (timer &optional dont-wait reuse-cell) 226(defun timer-activate-when-idle (timer &optional dont-wait reuse-cell)
216 "Arrange to activate TIMER whenever Emacs is next idle. 227 "Arrange to activate TIMER whenever Emacs is next idle.
217If optional argument DONT-WAIT is non-nil, then enable the 228If optional argument DONT-WAIT is non-nil, then enable the
@@ -220,36 +231,7 @@ is already idle.
220 231
221REUSE-CELL, if non-nil, is a cons cell to reuse instead 232REUSE-CELL, if non-nil, is a cons cell to reuse instead
222of allocating a new one." 233of allocating a new one."
223 (if (and (timerp timer) 234 (timer--activate timer (not dont-wait) reuse-cell 'idle))
224 (integerp (aref timer 1))
225 (integerp (aref timer 2))
226 (integerp (aref timer 3))
227 (aref timer 5))
228 (let ((timers timer-idle-list)
229 last)
230 ;; Skip all timers to trigger before the new one.
231 (while (and timers
232 (or (> (aref timer 1) (aref (car timers) 1))
233 (and (= (aref timer 1) (aref (car timers) 1))
234 (> (aref timer 2) (aref (car timers) 2)))
235 (and (= (aref timer 1) (aref (car timers) 1))
236 (= (aref timer 2) (aref (car timers) 2))
237 (> (aref timer 3) (aref (car timers) 3)))))
238 (setq last timers
239 timers (cdr timers)))
240 (if reuse-cell
241 (progn
242 (setcar reuse-cell timer)
243 (setcdr reuse-cell timers))
244 (setq reuse-cell (cons timer timers)))
245 ;; Insert new timer after last which possibly means in front of queue.
246 (if last
247 (setcdr last reuse-cell)
248 (setq timer-idle-list reuse-cell))
249 (aset timer 0 (not dont-wait))
250 (aset timer 7 t)
251 nil)
252 (error "Invalid or uninitialized timer")))
253 235
254(defalias 'disable-timeout 'cancel-timer) 236(defalias 'disable-timeout 'cancel-timer)
255 237
@@ -278,16 +260,12 @@ that was removed from the timer list."
278This affects ordinary timers such as are scheduled by `run-at-time', 260This affects ordinary timers such as are scheduled by `run-at-time',
279and idle timers such as are scheduled by `run-with-idle-timer'." 261and idle timers such as are scheduled by `run-with-idle-timer'."
280 (interactive "aCancel timers of function: ") 262 (interactive "aCancel timers of function: ")
281 (let ((tail timer-list)) 263 (dolist (timer timer-list)
282 (while tail 264 (if (eq (timer--function timer) function)
283 (if (eq (aref (car tail) 5) function) 265 (setq timer-list (delq timer timer-list))))
284 (setq timer-list (delq (car tail) timer-list))) 266 (dolist (timer timer-idle-list)
285 (setq tail (cdr tail)))) 267 (if (eq (timer--function timer) function)
286 (let ((tail timer-idle-list)) 268 (setq timer-idle-list (delq timer timer-idle-list)))))
287 (while tail
288 (if (eq (aref (car tail) 5) function)
289 (setq timer-idle-list (delq (car tail) timer-idle-list)))
290 (setq tail (cdr tail)))))
291 269
292;; Record the last few events, for debugging. 270;; Record the last few events, for debugging.
293(defvar timer-event-last nil 271(defvar timer-event-last nil
@@ -308,8 +286,9 @@ how many will really happen.")
308 "Calculate number of seconds from when TIMER will run, until TIME. 286 "Calculate number of seconds from when TIMER will run, until TIME.
309TIMER is a timer, and stands for the time when its next repeat is scheduled. 287TIMER is a timer, and stands for the time when its next repeat is scheduled.
310TIME is a time-list." 288TIME is a time-list."
311 (let ((high (- (car time) (aref timer 1))) 289 ;; FIXME: (time-to-seconds (time-subtract (timer--time timer) time))
312 (low (- (nth 1 time) (aref timer 2)))) 290 (let ((high (- (car time) (timer--high-seconds timer)))
291 (low (- (nth 1 time) (timer--low-seconds timer))))
313 (+ low (* high 65536)))) 292 (+ low (* high 65536))))
314 293
315(defun timer-event-handler (timer) 294(defun timer-event-handler (timer)
@@ -324,29 +303,30 @@ This function is called, by name, directly by the C code."
324 ;; Delete from queue. Record the cons cell that was used. 303 ;; Delete from queue. Record the cons cell that was used.
325 (setq cell (cancel-timer-internal timer)) 304 (setq cell (cancel-timer-internal timer))
326 ;; Re-schedule if requested. 305 ;; Re-schedule if requested.
327 (if (aref timer 4) 306 (if (timer--repeat-delay timer)
328 (if (aref timer 7) 307 (if (timer--idle-delay timer)
329 (timer-activate-when-idle timer nil cell) 308 (timer-activate-when-idle timer nil cell)
330 (timer-inc-time timer (aref timer 4) 0) 309 (timer-inc-time timer (timer--repeat-delay timer) 0)
331 ;; If real time has jumped forward, 310 ;; If real time has jumped forward,
332 ;; perhaps because Emacs was suspended for a long time, 311 ;; perhaps because Emacs was suspended for a long time,
333 ;; limit how many times things get repeated. 312 ;; limit how many times things get repeated.
334 (if (and (numberp timer-max-repeats) 313 (if (and (numberp timer-max-repeats)
335 (< 0 (timer-until timer (current-time)))) 314 (< 0 (timer-until timer (current-time))))
336 (let ((repeats (/ (timer-until timer (current-time)) 315 (let ((repeats (/ (timer-until timer (current-time))
337 (aref timer 4)))) 316 (timer--repeat-delay timer))))
338 (if (> repeats timer-max-repeats) 317 (if (> repeats timer-max-repeats)
339 (timer-inc-time timer (* (aref timer 4) repeats))))) 318 (timer-inc-time timer (* (timer--repeat-delay timer)
319 repeats)))))
340 (timer-activate timer t cell) 320 (timer-activate timer t cell)
341 (setq retrigger t))) 321 (setq retrigger t)))
342 ;; Run handler. 322 ;; Run handler.
343 ;; We do this after rescheduling so that the handler function 323 ;; We do this after rescheduling so that the handler function
344 ;; can cancel its own timer successfully with cancel-timer. 324 ;; can cancel its own timer successfully with cancel-timer.
345 (condition-case nil 325 (condition-case nil
346 (apply (aref timer 5) (aref timer 6)) 326 (apply (timer--function timer) (timer--args timer))
347 (error nil)) 327 (error nil))
348 (if retrigger 328 (if retrigger
349 (aset timer 0 nil))) 329 (setf (timer--triggered timer) nil)))
350 (error "Bogus timer event")))) 330 (error "Bogus timer event"))))
351 331
352;; This function is incompatible with the one in levents.el. 332;; This function is incompatible with the one in levents.el.
@@ -500,11 +480,7 @@ The value is a list that the debugger can pass to `with-timeout-unsuspend'
500when it exits, to make these timers start counting again." 480when it exits, to make these timers start counting again."
501 (mapcar (lambda (timer) 481 (mapcar (lambda (timer)
502 (cancel-timer timer) 482 (cancel-timer timer)
503 (list timer 483 (list timer (time-subtract (timer--time timer) (current-time))))
504 (time-subtract
505 ;; The time that this timer will go off.
506 (list (aref timer 1) (aref timer 2) (aref timer 3))
507 (current-time))))
508 with-timeout-timers)) 484 with-timeout-timers))
509 485
510(defun with-timeout-unsuspend (timer-spec-list) 486(defun with-timeout-unsuspend (timer-spec-list)
@@ -565,5 +541,5 @@ If the user does not answer after SECONDS seconds, return DEFAULT-VALUE."
565 541
566(provide 'timer) 542(provide 'timer)
567 543
568;;; arch-tag: b1a9237b-7787-4382-9e46-8f2c3b3273e0 544;; arch-tag: b1a9237b-7787-4382-9e46-8f2c3b3273e0
569;;; timer.el ends here 545;;; timer.el ends here