]> mj.ucw.cz Git - libucw.git/commitdiff
Changed main_loop shutdown logic once again. The former mechanism with
authorMartin Mares <mj@ucw.cz>
Mon, 14 Nov 2005 20:06:49 +0000 (20:06 +0000)
committerMartin Mares <mj@ucw.cz>
Mon, 14 Nov 2005 20:06:49 +0000 (20:06 +0000)
a single global main_shutdown variable was too inflexible. I have given
all hooks a possibility to either invoke an immediate shutdown or a "soft"
shutdown which is activated if all hooks agree on it (the idea is that
different parts of a single program can have their local opinion on whether
there is more to do or not).

lib/mainloop.c
lib/mainloop.h

index 544a7b7d47ea8faf705ac060ac2249ef29d639bf..5b5fb45a8b2077f765aa3bcf73d23b5abc635ea3 100644 (file)
@@ -345,7 +345,7 @@ main_rebuild_poll_table(void)
   main_poll_table_obsolete = 0;
 }
 
-int
+void
 main_loop(void)
 {
   DBG("MAIN: Entering main_loop");
@@ -366,12 +366,24 @@ main_loop(void)
          DBG("MAIN: Timer %p expired at %Ld", tm, (long long) tm->expires);
          tm->handler(tm);
        }
+      int hook_min = HOOK_RETRY;
+      int hook_max = HOOK_SHUTDOWN;
       CLIST_WALK_DELSAFE(ho, main_hook_list, tmp)
        {
          DBG("MAIN: Hook %p", ho);
-         if (ho->handler(ho))
-           wake = 0;
+         int ret = ho->handler(ho);
+         hook_min = MIN(hook_min, ret);
+         hook_max = MAX(hook_max, ret);
        }
+      if (hook_min == HOOK_SHUTDOWN ||
+         hook_min == HOOK_DONE && hook_max == HOOK_DONE ||
+         main_shutdown)
+       {
+         DBG("MAIN: Shut down by %s", main_shutdown ? "main_shutdown" : "a hook");
+         return;
+       }
+      if (hook_max == HOOK_RETRY)
+       wake = 0;
       if (main_poll_table_obsolete)
        main_rebuild_poll_table();
       if (!clist_empty(&main_process_list))
@@ -395,19 +407,6 @@ main_loop(void)
              wake = 0;
            }
        }
-      if (clist_empty(&main_file_list) &&
-         clist_empty(&main_timer_list) &&
-         clist_empty(&main_hook_list) &&
-         clist_empty(&main_process_list))
-       {
-         DBG("MAIN: Nothing to do, exiting");
-         return 0;
-       }
-      if (main_shutdown)
-       {
-         DBG("MAIN: Shutdown");
-         return 1;
-       }
       /* FIXME: Here is a small race window where SIGCHLD can come unnoticed. */
       if ((tm = clist_head(&main_timer_list)) && tm->expires < wake)
        wake = tm->expires;
index a8626f0345c2672ef20883cb2edd2e2b6b05d83b..f321c2b5fc85e57402d1a4c2741b1deea26f2bcd 100644 (file)
@@ -71,10 +71,17 @@ void file_close_all(void);                  /* Close all known main_file's; frequently used bef
 
 struct main_hook {
   cnode n;
-  int (*handler)(struct main_hook *ho);                /* [*] Hook function; returns 1 if should be called again */
+  int (*handler)(struct main_hook *ho);                /* [*] Hook function; returns HOOK_xxx */
   void *data;                                  /* [*] For use by the handler */
 };
 
+enum main_hook_return {
+  HOOK_IDLE,                                   /* Call again when the main loop becomes idle again */
+  HOOK_RETRY,                                  /* Call again as soon as possible */
+  HOOK_DONE = -1,                              /* Shut down the main loop if all hooks return this value */
+  HOOK_SHUTDOWN = -2                           /* Shut down the main loop immediately */
+};
+
 void hook_add(struct main_hook *ho);
 void hook_del(struct main_hook *ho);
 
@@ -96,7 +103,7 @@ int process_fork(struct main_process *mp);
 /* The main loop */
 
 void main_init(void);
-int main_loop(void);
+void main_loop(void);
 void main_debug(void);
 
 #endif