updates. New data types.
[silc.git] / lib / silcutil / silcschedule.c
index 0cbf333e21ae98267f2a58f6f32ea94fe479af9b..4a7522200075ba941c353f8c7c07570449c697a3 100644 (file)
   GNU General Public License for more details.
 
 */
-/*
- * $Id$
- * $Log$
- * Revision 1.1  2000/09/13 17:45:16  priikone
- *     Splitted SILC core library. Core library includes now only
- *     SILC protocol specific stuff. New utility library includes the
- *     old stuff from core library that is more generic purpose stuff.
- *
- * Revision 1.3  2000/07/18 06:51:58  priikone
- *     Debug version bug fixes.
- *
- * Revision 1.2  2000/07/05 06:06:35  priikone
- *     Global cosmetic change.
- *
- * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
- *     Imported from internal CVS/Added Log headers.
- *
- *
- */
+/* $Id$ */
 
 #include "silcincludes.h"
 
@@ -137,7 +119,7 @@ void silc_schedule_stop()
    call this directly if wanted. This can be called multiple times for
    one file descriptor to set different iomasks. */
 
-void silc_schedule_set_listen_fd(int fd, unsigned int iomask)
+void silc_schedule_set_listen_fd(int fd, uint32 iomask)
 {
   assert(schedule.valid != FALSE);
   assert(fd < schedule.fd_list.max_fd);
@@ -164,7 +146,7 @@ void silc_schedule_unset_listen_fd(int fd)
       if (schedule.fd_list.fd[i] != -1)
        break;
 
-    schedule.fd_list.last_fd = i;
+    schedule.fd_list.last_fd = i < 0 ? 0 : i;
   }
 }
 
@@ -438,84 +420,95 @@ do {                                                                           \
   }                                                                         \
 } while(0)
 
-/* The SILC scheduler. This is actually the main routine in SILC programs.
-   When this returns the program is to be ended. Before this function can
-   be called, one must call silc_schedule_init function. */
-
-void silc_schedule()
+int silc_schedule_one(int timeout_usecs)
 {
+  struct timeval timeout;
   int is_run, i;
   SilcTask task;
   SilcTaskQueue queue;
   struct timeval curtime;
 
-  SILC_LOG_DEBUG(("Running scheduler"));
+  SILC_LOG_DEBUG(("In scheduler loop"));
 
-  if (schedule.valid == FALSE) {
-    SILC_LOG_ERROR(("Scheduler is not valid, stopping"));
-    return;
+  /* If the task queues aren't initialized or we aren't valid anymore
+     we will return */
+  if ((!schedule.fd_queue && !schedule.timeout_queue 
+       && !schedule.generic_queue) || schedule.valid == FALSE) {
+    SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting"));
+    return FALSE;
   }
 
-  /* Start the scheduler loop */
-  while(1) {
+  /* Clear everything */
+  FD_ZERO(&schedule.in);
+  FD_ZERO(&schedule.out);
+  schedule.max_fd = -1;
+  is_run = FALSE;
 
-    SILC_LOG_DEBUG(("In scheduler loop"));
+  /* Calculate next timeout for select(). This is the timeout value
+     when at earliest some of the timeout tasks expire. */
+  SILC_SCHEDULE_SELECT_TIMEOUT;
 
-    /* If the task queues aren't initialized or we aren't valid anymore
-       we will return */
-    if ((!schedule.fd_queue && !schedule.timeout_queue 
-        && !schedule.generic_queue) || schedule.valid == FALSE) {
-      SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting"));
-      break;
-    }
+  /* Add the file descriptors to the fd sets. These are the non-timeout
+     tasks. The select() listens to these file descriptors. */
+  SILC_SCHEDULE_SELECT_TASKS;
 
-    /* Clear everything */
-    FD_ZERO(&schedule.in);
-    FD_ZERO(&schedule.out);
-    schedule.max_fd = -1;
-    is_run = FALSE;
+  if (schedule.max_fd == -1 && !schedule.timeout)
+    return FALSE;
 
-    /* Calculate next timeout for select(). This is the timeout value
-       when at earliest some of the timeout tasks expire. */
-    SILC_SCHEDULE_SELECT_TIMEOUT;
+  if (schedule.timeout) {
+    SILC_LOG_DEBUG(("timeout: sec=%d, usec=%d", schedule.timeout->tv_sec,
+                   schedule.timeout->tv_usec));
+  }
 
-    /* Add the file descriptors to the fd sets. These are the non-timeout
-       tasks. The select() listens to these file descriptors. */
-    SILC_SCHEDULE_SELECT_TASKS;
+  if (timeout_usecs >= 0) {
+    timeout.tv_sec = 0;
+    timeout.tv_usec = timeout_usecs;
+    schedule.timeout = &timeout;
+  }
 
-    if (schedule.max_fd == -1) {
-      SILC_LOG_ERROR(("Nothing to listen, exiting"));
+  /* This is the main select(). The program blocks here until some
+     of the selected file descriptors change status or the selected
+     timeout expires. */
+  SILC_LOG_DEBUG(("Select"));
+  switch (select(schedule.max_fd + 1, &schedule.in,
+                &schedule.out, 0, schedule.timeout)) {
+  case -1:
+    /* Error */
+    if (errno == EINTR)
       break;
-    }
-
-    if (schedule.timeout) {
-      SILC_LOG_DEBUG(("timeout: sec=%d, usec=%d", schedule.timeout->tv_sec,
-                     schedule.timeout->tv_usec));
-    }
-
-    /* This is the main select(). The program blocks here until some
-       of the selected file descriptors change status or the selected
-       timeout expires. */
-    SILC_LOG_DEBUG(("Select"));
-    switch(select(schedule.max_fd + 1, &schedule.in, 
-                 &schedule.out, 0, schedule.timeout)) {
-    case -1:
-      /* Error */
-      SILC_LOG_ERROR(("Error in select(): %s", strerror(errno)));
-      break;
-    case 0:
-      /* Timeout */
-      SILC_LOG_DEBUG(("Running timeout tasks"));
-      gettimeofday(&curtime, NULL);
-      SILC_SCHEDULE_RUN_TIMEOUT_TASKS;
-      break;
-    default:
-      /* There is some data available now */
-      SILC_LOG_DEBUG(("Running non-timeout tasks"));
-      SILC_SCHEDULE_RUN_TASKS;
+    SILC_LOG_ERROR(("Error in select(): %s", strerror(errno)));
+    break;
+  case 0:
+    /* Timeout */
+    SILC_LOG_DEBUG(("Running timeout tasks"));
+    gettimeofday(&curtime, NULL);
+    SILC_SCHEDULE_RUN_TIMEOUT_TASKS;
+    break;
+  default:
+    /* There is some data available now */
+    SILC_LOG_DEBUG(("Running non-timeout tasks"));
+    SILC_SCHEDULE_RUN_TASKS;
+
+    SILC_SCHEDULE_RUN_GENERIC_TASKS;
+    break;
+  }
+  return TRUE;
+}
 
-      SILC_SCHEDULE_RUN_GENERIC_TASKS;
-      break;
-    }
+/* The SILC scheduler. This is actually the main routine in SILC programs.
+   When this returns the program is to be ended. Before this function can
+   be called, one must call silc_schedule_init function. */
+
+void silc_schedule()
+{
+  SILC_LOG_DEBUG(("Running scheduler"));
+
+  if (schedule.valid == FALSE) {
+    SILC_LOG_ERROR(("Scheduler is not valid, stopping"));
+    return;
   }
+
+  /* Start the scheduler loop */
+  while (silc_schedule_one(-1)) 
+    ;
 }