emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Should `cancel-timer' use `delete' instead of `delq'?


From: Drew Adams
Subject: RE: Should `cancel-timer' use `delete' instead of `delq'?
Date: Tue, 5 Sep 2006 09:20:43 -0700

    >    If the use of delq (vector identity) in `cancel-timer'
    >    is intentional and it is considered a feature to have
    >    multiple idle timers with the same parameters, then
    >    perhaps the doc should warn people of this gotcha -
    >    perhaps advise them to use `cancel-timer' first, before
    >    `run-with-idle-timer':

    > It's almost certainly intentional that it uses delq.
    > A timer is a unique entity.

    > If application code can create multiple timers and doesn't
    > save all the corresponding cookies for deletion, it's obviously
    > a bug in that application code.

    While I somewhat agree with Miles, I also agree with Drew that
    it can lead to undesirable situations where it's very difficult
    to return to a "normal" session, other than by restarting Emacs.

    I've been tempted to change timer-idle-list and timer-list so
    that they use weak-pointers.  I.e. if you don't hold on to your
    timer by storing it in a global var or somesuch, then it'll get
    cancelled/destroyed at the next GC.
    I think this could work if we only do it for timers that use `repeat'.

Hard to agree with me ;-): I just asked a question - I didn't know what the
intention was.

What you suggest sounds good to me, though I'm pretty ignorant of this
stuff.

I think, though, that it still might make sense to document the gotcha; who
knows when the next GC will take place, and that could make the behavior
seem even more erratic (sometimes the timer is here, sometimes it's gone,
depending on a GC).

I don't know if this is a good way to handle the gotcha, but this is what
I've resorted to in my code (until I get a better suggestion):

(defvar foo-timer
  (progn ; Cancel to prevent ~duplication.
    (when (boundp 'foo-timer) (cancel-timer foo-timer))
    (run-with-idle-timer 2 t 'foo))
  "Timer used to foo whenever Emacs is idle.")

;; Turn it off, by default. You must use `toggle-foo' to turn it on.
(cancel-timer foo-timer)

Does it make sense to suggest doing something like this in Lisp code? Or at
least to point out that you probably don't want to eval
`run-with-idle-timer' without first cancelling a structurally equivalent
(but not eq) timer, if one already exists? Would we then also need to
explain that GC will eliminate any timers that are no longer held by
variables?

I'm not necessarily suggesting this change, but another possibility might be
to create and recommend (for most purposes) using a `define-idle-timer'
macro, instead of `run-with-idle-timer'. The macro would do more or less
what the above code does. That would ensure that the new timer was
associated with a variable and there were no zombie pseudo-duplicate timers
still running - each timer would have a unique name (associated variable).

The macro might even take an arg that determined whether the timer was to
start life running or cancelled. The macro would thus also let you
dissociate creation of the timer from activating it.

Further, the macro might, optionally, also create a toggle command that
would turn the timer on and off using `timer-activate-when-idle' and
`cancel-timer'. A la `define-minor-mode', with a message echoing the new
state and an internal variable `foo-activate-when-idle-p' that gets toggled.
That would be useful for some cases but not others, of course.

If we wanted to get more sophisticated, the macro could optionally take
additional Lisp code as input to include in each of the branches of the
toggle command. For example, if you wanted to add and remove a hook function
in the toggle-command branches, you could pass in the code to do that as
well.

People who wanted to use `run-with-idle-timer' directly could still do so,
of course, but most people would then use `define-idle-timer', which
prevents the gotcha.

Again, I'm no expert on timers. If this makes little sense, please ignore.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]