]> git.eshelyaron.com Git - emacs.git/commitdiff
(timer_check): Walk down both timer lists in parallel.
authorRichard M. Stallman <rms@gnu.org>
Wed, 28 Feb 1996 17:51:22 +0000 (17:51 +0000)
committerRichard M. Stallman <rms@gnu.org>
Wed, 28 Feb 1996 17:51:22 +0000 (17:51 +0000)
src/keyboard.c

index 06a66327fdf9163823db311d9e8c61b68fac2fe0..e7432239103cba305935df491bcefe1e3148e139 100644 (file)
@@ -2922,136 +2922,211 @@ timer_stop_idle ()
    timer is triggering now, return zero seconds.
    If no timer is active, return -1 seconds.
 
-   If a timer is triggering now, either queue a timer-event
-   or run the timer's handler function if DO_IT_NOW is nonzero.  */
+   If a timer is ripe now, either queue a timer-event,
+   or call the timer's handler function here if DO_IT_NOW is nonzero.  */
 
 EMACS_TIME
 timer_check (do_it_now)
      int do_it_now;
 {
   EMACS_TIME nexttime;
-  EMACS_TIME now;
-  Lisp_Object timers, timer;
+  EMACS_TIME now, idleness_now;
+  Lisp_Object timers, idle_timers, chosen_timer;
   /* Nonzero if we generate some events.  */
   int events_generated = 0;
-  struct gcpro gcpro1, gcpro2;
-  int listnum;
+  struct gcpro gcpro1, gcpro2, gcpro3;
 
   EMACS_SET_SECS (nexttime, -1);
   EMACS_SET_USECS (nexttime, -1);
 
+  /* Always consider the ordinary timers.  */
   timers = Vtimer_list;
-  timer = Qnil;
-  GCPRO2 (timers, timer);
-
-  if (CONSP (Vtimer_list) || CONSP (Vtimer_idle_list))
-    EMACS_GET_TIME (now);
+  /* Consider the idle timers only if Emacs is idle.  */
+  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+    idle_timers = Vtimer_idle_list;
+  else
+    idle_timers = Qnil;
+  chosen_timer = Qnil;
+  GCPRO3 (timers, idle_timers, chosen_timer);
 
-  for (listnum = 0; listnum < 2; listnum++)
+  if (CONSP (timers) || CONSP (idle_timers))
     {
-      EMACS_TIME compare_time;
-
-      /* Always first scan the absolute timer list.  */
-      if (listnum == 0)
-       {
-         timers = Vtimer_list;
-         compare_time = now;
-       }
-      /* If Emacs is idle, scan the idle timer list
-        using the length of idleness as the time value.  */
-      else if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
-       {
-         timers = Vtimer_idle_list;
-         EMACS_SUB_TIME (compare_time, now, timer_idleness_start_time);
-       }
-      else
-       break;
+      EMACS_GET_TIME (now);
+      if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+       EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
+    }
 
-      while (CONSP (timers))
+  while (CONSP (timers) || CONSP (idle_timers))
+    {
+      int triggertime = EMACS_SECS (now);
+      Lisp_Object *vector;
+      Lisp_Object timer, idle_timer;
+      EMACS_TIME timer_time, idle_timer_time;
+      EMACS_TIME difference, timer_difference, idle_timer_difference;
+
+      /* Skip past invalid timers and timers already handled.  */
+      if (!NILP (timers))
        {
-         int triggertime = EMACS_SECS (now);
-         Lisp_Object *vector;
-         EMACS_TIME timer_time;
-         EMACS_TIME difference;
-
          timer = XCONS (timers)->car;
-         timers = XCONS (timers)->cdr;
+         if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+           {
+             timers = XCONS (timers)->cdr;
+             continue;
+           }
+         vector = XVECTOR (timer)->contents;
 
+         if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
+             || !INTEGERP (vector[3])
+             || ! NILP (vector[0]))
+           {
+             timers = XCONS (timers)->cdr;
+             continue;
+           }
+       }
+      if (!NILP (idle_timers))
+       {
+         timer = XCONS (idle_timers)->car;
          if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
-           continue;
+           {
+             idle_timers = XCONS (idle_timers)->cdr;
+             continue;
+           }
          vector = XVECTOR (timer)->contents;
 
          if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
-             || !INTEGERP (vector[3]))
-           continue;
+             || !INTEGERP (vector[3])
+             || ! NILP (vector[0]))
+           {
+             idle_timers = XCONS (idle_timers)->cdr;
+             continue;
+           }
+       }
 
+      /* Set TIMER, TIMER_TIME and TIMER_DIFFERENCE
+        based on the next ordinary timer.
+        TIMER_DIFFERENCE is the distance in time from NOW to when
+        this timer becomes ripe (negative if it's already ripe).  */
+      if (!NILP (timers))
+       {
+         timer = XCONS (timers)->car;
+         vector = XVECTOR (timer)->contents;
          EMACS_SET_SECS (timer_time,
                          (XINT (vector[1]) << 16) | (XINT (vector[2])));
          EMACS_SET_USECS (timer_time, XINT (vector[3]));
-         EMACS_SUB_TIME (difference, timer_time, compare_time);
-         /* If event is past, run it if it hasn't been run.  */
-         if (EMACS_TIME_NEG_P (difference)
-             || (EMACS_SECS (difference) == 0
-                 && EMACS_USECS (difference) == 0))
-           {
-             if (NILP (vector[0]))
-               {
-                 /* Mark the timer as triggered to prevent problems if the lisp
-                    code fails to reschedule it right.  */
-                 vector[0] = Qt;
-
-                 /* Run the timer or queue a timer event.  */
-                 if (do_it_now)
-                   {
-                     Lisp_Object tem, event;
-                     int was_locked = single_kboard;
+         EMACS_SUB_TIME (timer_difference, timer_time, now);
+       }
 
-                     tem = get_keymap_1 (Vspecial_event_map, 0, 0);
-                     tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
-                                       1);
-                     event = Fcons (Qtimer_event, Fcons (timer, Qnil));
-                     Fcommand_execute (tem, Qnil, Fvector (1, &event), Qt);
+      /* Set IDLE_TIMER, IDLE_TIMER_TIME and IDLE_TIMER_DIFFERENCE
+        based on the next idle timer.  */
+      if (!NILP (idle_timers))
+       {
+         idle_timer = XCONS (idle_timers)->car;
+         vector = XVECTOR (idle_timer)->contents;
+         EMACS_SET_SECS (idle_timer_time,
+                         (XINT (vector[1]) << 16) | (XINT (vector[2])));
+         EMACS_SET_USECS (idle_timer_time, XINT (vector[3]));
+         EMACS_SUB_TIME (idle_timer_difference, idle_timer_time, idleness_now);
+       }
 
-                     /* Resume allowing input from any kboard, if that was true before.  */
-                     if (!was_locked)
-                       any_kboard_state ();
+      /* Decide which timer is the next timer,
+        and set CHOSEN_TIMER, VECTOR and DIFFERENCE accordingly.
+        Also step down the list where we found that timer.  */
 
-                     /* Since we have handled the event,
-                        we don't need to tell the caller to wake up and do it.  */
-                   }
-                 else
-                   {
-                     /* Generate a timer event so the caller will handle it.  */
-                     struct input_event event;
-
-                     event.kind = timer_event;
-                     event.modifiers = 0;
-                     event.x = event.y = Qnil;
-                     event.timestamp = triggertime;
-                     /* Store the timer in the frame slot.  */
-                     event.frame_or_window = Fcons (Fselected_frame (), timer);
-                     kbd_buffer_store_event (&event);
-
-                     /* Tell caller to handle this event right away.  */
-                     events_generated = 1;
-                     EMACS_SET_SECS (nexttime, 0);
-                     EMACS_SET_USECS (nexttime, 0);
-                   }
-               }
+      if (! NILP (timers) && ! NILP (idle_timers))
+       {
+         EMACS_TIME temp;
+         EMACS_SUB_TIME (temp, timer_difference, idle_timer_difference);
+         if (EMACS_TIME_NEG_P (temp))
+           {
+             chosen_timer = timer;
+             timers = XCONS (timers)->cdr;
+             difference = timer_difference;
            }
          else
-           /* When we encounter a timer that is still waiting,
-              return the amount of time to wait before it is ripe.  */
            {
-             UNGCPRO;
-             /* But if we generated an event,
-                tell the caller to handle it now.  */
-             if (events_generated)
-               return nexttime;
-             return difference;
+             chosen_timer = idle_timer;
+             idle_timers = XCONS (idle_timers)->cdr;
+             difference = idle_timer_difference;
            }
        }
+      else if (! NILP (timers))
+       {
+         chosen_timer = timer;
+         timers = XCONS (timers)->cdr;
+         difference = timer_difference;
+       }
+      else
+       {
+         chosen_timer = idle_timer;
+         idle_timers = XCONS (idle_timers)->cdr;
+         difference = idle_timer_difference;
+       }
+      vector = XVECTOR (chosen_timer)->contents;
+       
+      /* If timer is rupe, run it if it hasn't been run.  */
+      if (EMACS_TIME_NEG_P (difference)
+         || (EMACS_SECS (difference) == 0
+             && EMACS_USECS (difference) == 0))
+       {
+         if (NILP (vector[0]))
+           {
+             /* Mark the timer as triggered to prevent problems if the lisp
+                code fails to reschedule it right.  */
+             vector[0] = Qt;
+
+             /* Run the timer or queue a timer event.  */
+             if (do_it_now)
+               {
+                 Lisp_Object tem, event;
+                 int was_locked = single_kboard;
+
+                 tem = get_keymap_1 (Vspecial_event_map, 0, 0);
+                 tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
+                                   1);
+                 event = Fcons (Qtimer_event, Fcons (chosen_timer, Qnil));
+                 Fcommand_execute (tem, Qnil, Fvector (1, &event), Qt);
+
+                 /* Resume allowing input from any kboard, if that was true before.  */
+                 if (!was_locked)
+                   any_kboard_state ();
+
+                 /* Since we have handled the event,
+                    we don't need to tell the caller to wake up and do it.  */
+               }
+             else
+               {
+                 /* Generate a timer event so the caller will handle it.  */
+                 struct input_event event;
+
+                 event.kind = timer_event;
+                 event.modifiers = 0;
+                 event.x = event.y = Qnil;
+                 event.timestamp = triggertime;
+                 /* Store the timer in the frame slot.  */
+                 event.frame_or_window
+                   = Fcons (Fselected_frame (), chosen_timer);
+                 kbd_buffer_store_event (&event);
+
+                 /* Tell caller to handle this event right away.  */
+                 events_generated = 1;
+                 EMACS_SET_SECS (nexttime, 0);
+                 EMACS_SET_USECS (nexttime, 0);
+               }
+           }
+       }
+      else
+       /* When we encounter a timer that is still waiting,
+          return the amount of time to wait before it is ripe.  */
+       {
+         UNGCPRO;
+         /* But if we generated an event,
+            tell the caller to handle it now.  */
+         if (events_generated)
+           return nexttime;
+         return difference;
+       }
     }
+
   /* No timers are pending in the future.  */
   /* Return 0 if we generated an event, and -1 if not.  */
   UNGCPRO;