]> code.delx.au - gnu-emacs/blobdiff - src/atimer.c
(custom-set-variables): Set options with :require
[gnu-emacs] / src / atimer.c
index 92f5076fcc70394dd43746be9f96bb84174c99c9..54a038fd549687340416535f8319e88aac97cd3c 100644 (file)
@@ -44,6 +44,11 @@ Boston, MA 02111-1307, USA.  */
 
 static struct atimer *free_atimers;
 
+/* List of currently not running timers due to a call to
+   lock_atimer.  */
+
+static struct atimer *stopped_atimers;
+
 /* List of active atimers, sorted by expiration time.  The timer that
    will become ripe next is always at the front of this list.  */
 
@@ -66,6 +71,9 @@ int pending_atimers;
 
 static void set_alarm P_ ((void));
 static void schedule_atimer P_ ((struct atimer *));
+static struct atimer *append_atimer_lists P_ ((struct atimer *,
+                                              struct atimer *));
+SIGTYPE alarm_signal_handler ();
 
 
 /* Start a new atimer of type TYPE.  TIME specifies when the timer is
@@ -100,8 +108,8 @@ start_atimer (type, time, fn, client_data)
 #ifndef HAVE_SETITIMER
   if (EMACS_USECS (time) != 0)
     {
-      EMACS_USECS (time) = 0;
-      ++EMACS_SECS (time);
+      EMACS_SET_USECS (time, 0);
+      EMACS_SET_SECS (time, EMACS_SECS (time) + 1);
     }
 #endif /* not HAVE_SETITIMER */
 
@@ -159,29 +167,132 @@ void
 cancel_atimer (timer)
      struct atimer *timer;
 {
-  struct atimer *t, *prev;
-
+  int i;
+  
   BLOCK_ATIMERS;
 
-  /* See if TIMER is active.  */
-  for (t = atimers, prev = 0; t && t != timer; t = t->next)
-    ;
+  for (i = 0; i < 2; ++i)
+    {
+      struct atimer *t, *prev;
+      struct atimer **list = i ? &stopped_atimers : &atimers;
+      
+      /* See if TIMER is active or stopped.  */
+      for (t = *list, prev = NULL; t && t != timer; prev = t, t = t->next)
+       ;
+
+      /* If it is, take it off the its list, and put in on the
+        free-list.  We don't bother to arrange for setting a
+        different alarm time, since a too early one doesn't hurt.  */
+      if (t)
+       {
+         if (prev)
+           prev->next = t->next;
+         else
+           *list = t->next;
+         
+         t->next = free_atimers;
+         free_atimers = t;
+         break;
+       }
+    }
+
+  UNBLOCK_ATIMERS;
+}
+
 
-  /* If it is, take it off the list of active timers, put in on the
-     free-list.  We don't bother to arrange for setting a different
-     alarm time, since a too early one doesn't hurt.  */
+/* Append two lists of atimers LIST1 and LIST2 and return the
+   result list.  */
+
+static struct atimer *
+append_atimer_lists (list1, list2)
+     struct atimer *list1, *list2;
+{
+  if (list1 == NULL)
+    return list2;
+  else if (list2 == NULL)
+    return list1;
+  else
+    {
+      struct atimer *p;
+      
+      for (p = list1; p->next; p = p->next)
+       ;
+      p->next = list2;
+      return list1;
+    }
+}
+
+
+/* Stop all timers except timer T.  T null means stop all timers.  */
+
+void
+stop_other_atimers (t)
+     struct atimer *t;
+{
+  BLOCK_ATIMERS;
+  
   if (t)
     {
-      if (prev)
-       prev->next = t->next;
+      struct atimer *p, *prev;
+      
+      /* See if T is active.  */
+      for (p = atimers, prev = 0; p && p != t; p = p->next)
+       ;
+
+      if (p == t)
+       {
+         if (prev)
+           prev->next = t->next;
+         else
+           atimers = t->next;
+         t->next = NULL;
+       }
       else
-       atimers = t->next;
+       /* T is not active.  Let's handle this like T == 0.  */
+       t = NULL;
+    }
+  
+  stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
+  atimers = t;
+  UNBLOCK_ATIMERS;
+}
+
+
+/* Run all timers again, if some have been stopped with a call to
+   stop_other_atimers.  */
 
-      t->next = free_atimers;
-      free_atimers = t;
+void
+run_all_atimers ()
+{
+  if (stopped_atimers)
+    {
+      struct atimer *t = atimers;
+      struct atimer *next;
+      
+      BLOCK_ATIMERS;
+      atimers = stopped_atimers;
+      stopped_atimers = NULL;
+      
+      while (t)
+       {
+         next = t->next;
+         schedule_atimer (t);
+         t = next;
+       }
+      
+      UNBLOCK_ATIMERS;
     }
+}
 
-  UNBLOCK_ATIMERS;
+
+/* A version of run_all_timers suitable for a record_unwind_protect.  */
+
+Lisp_Object
+unwind_stop_other_atimers (dummy)
+     Lisp_Object dummy;
+{
+  run_all_atimers ();
+  return Qnil;
 }
 
 
@@ -190,7 +301,6 @@ cancel_atimer (timer)
 static void
 set_alarm ()
 {
-  
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
      must reestablish each time.  */