Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / silcschedule.h
index b0e315fda678cb64bd727b3c2348587ecd4e52bd..be24c41a20c8df5864d258a288381264dffe3688 100644 (file)
@@ -2,16 +2,13 @@
   
   silcschedule.h
  
-  COPYRIGHT
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1998 - 2001 Pekka Riikonen
+  Copyright (C) 1998 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +17,7 @@
 
 */
  
-/****h* silcutil/SilcScheduleAPI
+/****h* silcutil/SILC Schedule Interface
  *
  * DESCRIPTION
  *
@@ -119,8 +116,8 @@ typedef struct SilcTaskStruct *SilcTask;
 typedef enum {
   /* File descriptor task that performs some event over file descriptors.
      These tasks are for example network connections. */
-  SILC_TASK_FD,
-  
+  SILC_TASK_FD           = 0,
+
   /* Timeout tasks are tasks that are executed after the specified 
      time has elapsed. After the task is executed the task is removed
      automatically from the scheduler. It is safe to re-register the
@@ -157,14 +154,16 @@ typedef enum {
  *    The SILC_TASK_READ and SILC_TASK_WRITE may be set by the caller
  *    of the silc_schedule_set_listen_fd, if the caller needs to control
  *    the events for the task. The SILC_TASK_EXPIRE is set always only
- *    by the scheduler when timeout expires for timeout task.
+ *    by the scheduler when timeout expires for timeout task.  The
+ *    SILC_TASK_INTERRUPT is set for signal callback.
  *
  * SOURCE
  */
 typedef enum {
-  SILC_TASK_READ      = 0x0001,                 /* Reading */
-  SILC_TASK_WRITE     = 0x0002,                 /* Writing */
-  SILC_TASK_EXPIRE    = 0x0004,                 /* Timeout */
+  SILC_TASK_READ         = 0x0001,              /* Reading */
+  SILC_TASK_WRITE        = 0x0002,              /* Writing */
+  SILC_TASK_EXPIRE       = 0x0004,              /* Timeout */
+  SILC_TASK_INTERRUPT    = 0x0008,              /* Signal */
 } SilcTaskEvent;
 /***/
 
@@ -188,7 +187,7 @@ typedef enum {
      has expired only and only when every other task with higher priority 
      has already been run. For non-timeout tasks this priority behaves
      same way. Life is not fair for tasks with this priority. */
-  SILC_TASK_PRI_LOW,
+  SILC_TASK_PRI_LOW      = 0,
 
   /* Normal priority that is used mostly in SILC. This is priority that
      should always be used unless you specificly need some other priority.
@@ -203,8 +202,9 @@ typedef enum {
  *
  * SYNOPSIS
  *
- *    typedef void (*SilcTaskCallback)(SilcSchedule schedule, 
- *                                     SilcTaskEvent type, SilcUInt32 fd, 
+ *    typedef void (*SilcTaskCallback)(SilcSchedule schedule,
+ *                                     void *app_context,
+ *                                     SilcTaskEvent type, SilcUInt32 fd,
  *                                     void *context);
  *
  * DESCRIPTION
@@ -216,15 +216,18 @@ typedef enum {
  *    The `schedule' is the scheduler context, the `type' is the indicated
  *    event, the `fd' is the file descriptor of the task and the `context'
  *    is a caller specified context. If multiple events occurred this
- *    callback is called separately for all events.
+ *    callback is called separately for all events.  The `app_context'
+ *    is application specific context that was given as argument to the
+ *    silc_schedule_init function.
  *
  *    To specify task callback function in the application using the
  *    SILC_TASK_CALLBACK and SILC_TASK_CALLBACK_GLOBAL macros is
  *    recommended.
  *
  ***/
-typedef void (*SilcTaskCallback)(SilcSchedule schedule, SilcTaskEvent type,
-                                SilcUInt32 fd, void *context);
+typedef void (*SilcTaskCallback)(SilcSchedule schedule, void *app_context,
+                                SilcTaskEvent type, SilcUInt32 fd,
+                                void *context);
 
 /* Macros */
 
@@ -258,7 +261,8 @@ typedef void (*SilcTaskCallback)(SilcSchedule schedule, SilcTaskEvent type,
  * SOURCE
  */
 #define SILC_TASK_CALLBACK(func)                               \
-static void func(SilcSchedule schedule, SilcTaskEvent type,    \
+static void func(SilcSchedule schedule, void *app_context,     \
+                SilcTaskEvent type,                            \
                 SilcUInt32 fd, void *context)
 /***/
 
@@ -277,8 +281,8 @@ static void func(SilcSchedule schedule, SilcTaskEvent type, \
  *
  * SOURCE
  */
-#define SILC_TASK_CALLBACK_GLOBAL(func)                        \
-void func(SilcSchedule schedule, SilcTaskEvent type,   \
+#define SILC_TASK_CALLBACK_GLOBAL(func)                                        \
+void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type,        \
          SilcUInt32 fd, void *context)
 /***/
 
@@ -288,17 +292,20 @@ void func(SilcSchedule schedule, SilcTaskEvent type,      \
  *
  * SYNOPSIS
  *
- *    SilcSchedule silc_schedule_init(int max_tasks);
+ *    SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
  *
  * DESCRIPTION
  *
  *    Initializes the scheduler. This returns the scheduler context that
  *    is given as argument usually to all silc_schedule_* functions.
  *    The `max_tasks' indicates the number of maximum tasks that the
- *    scheduler can handle.
+ *    scheduler can handle. The `app_context' is application specific
+ *    context that is delivered to all task callbacks. The caller must
+ *    free that context.  The 'app_context' can be for example the
+ *    application itself.
  *
  ***/
-SilcSchedule silc_schedule_init(int max_tasks);
+SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_uninit
  *
@@ -405,6 +412,22 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
  ***/
 void silc_schedule_wakeup(SilcSchedule schedule);
 
+/****f* silcutil/SilcScheduleAPI/silc_schedule_get_context
+ *
+ * SYNOPSIS
+ *
+ *    void *silc_schedule_get_context(SilcSchedule schedule);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the application specific context that was saved into the
+ *    scheduler in silc_schedule_init function.  The context is also
+ *    returned to application in task callback functions, but this function
+ *    may be used to get it as well if needed.
+ *
+ ***/
+void *silc_schedule_get_context(SilcSchedule schedule);
+
 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add
  *
  * SYNOPSIS
@@ -537,7 +560,7 @@ void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
  * SYNOPSIS
  *
  *    void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
- *                                     SilcTaskEvent mask);
+ *                                     SilcTaskEvent mask, bool send_events);
  *
  * DESCRIPTION
  *
@@ -550,9 +573,14 @@ void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
  *    whenever you need to change the events. This can be called multiple
  *    times to change the events.
  *
+ *    If the `send_events' is TRUE then this function sends the events
+ *    in `mask' to the application.  If FALSE then they are sent only
+ *    after the event occurs in reality.  In normal cases the `send_events'
+ *    is set to FALSE.
+ *
  ***/
 void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
-                                SilcTaskEvent mask);
+                                SilcTaskEvent mask, bool send_events);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_unset_listen_fd
  *
@@ -569,4 +597,93 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
  ***/
 void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd);
 
+/****f* silcutil/SilcScheduleAPI/silc_schedule_signal_register
+ *
+ * SYNOPSIS
+ *
+ *    void silc_schedule_signal_register(SilcSchedule schedule, 
+ *                                       SilcUInt32 signal,
+ *                                      SilcTaskCallback callback,
+ *                                      void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Register signal indicated by `signal' to the scheduler.  Application
+ *    should register all signals it is going to use to the scheduler.
+ *    The `callback' with `context' will be called after the application
+ *    has called silc_schedule_signal_call function in the real signal 
+ *    callback.  Application is responsible of calling that, and the 
+ *    signal system will not work without calling silc_schedule_signal_call
+ *    function.  The specified `signal' value will be also delivered to
+ *    the `callback' as the fd-argument.  The event type in the callback
+ *    will be SILC_TASK_INTERRUPT.  It is safe to use any SILC routines
+ *    in the `callback' since it is actually called after the signal really
+ *    happened.
+ *
+ *    On platform that does not support signals calling this function has 
+ *    no effect.
+ *
+ * EXAMPLE
+ *
+ *    Typical signal usage case on Unix systems:
+ *
+ *    struct sigaction sa;
+ *    sa.sa_handler = signal_handler;
+ *    sigaction(SIGHUP, &sa, NULL);
+ *    sigaction(SIGINT, &sa, NULL);
+ *    silc_schedule_signal_register(schedule, SIGHUP, hup_signal, context);
+ *    silc_schedule_signal_register(schedule, SIGINT, int_signal, context);
+ *
+ *    static void signal_handler(int sig)
+ *    {
+ *      silc_schedule_signal_call(schedule, sig);
+ *    }
+ *
+ *    The `signal_handler' can be used as generic signal callback in the
+ *    application that merely calls silc_schedule_signal_call, which then
+ *    eventually will deliver for example the `hup_signal' callback.  The 
+ *    same `signal_handler' can be used with all signals.
+ *
+ ***/
+void silc_schedule_signal_register(SilcSchedule schedule, SilcUInt32 signal,
+                                  SilcTaskCallback callback, void *context);
+
+/****f* silcutil/SilcScheduleAPI/silc_schedule_signal_unregister
+ *
+ * SYNOPSIS
+ *
+ *    void silc_schedule_signal_unregister(SilcSchedule schedule, 
+ *                                         SilcUInt32 signal,
+ *                                        SilcTaskCallback callback,
+ *                                        void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Unregister a signal indicated by `signal' from the scheduler.  On
+ *    platform that does not support signals calling this function has no
+ *    effect.
+ *
+ ***/
+void silc_schedule_signal_unregister(SilcSchedule schedule, SilcUInt32 signal,
+                                    SilcTaskCallback callback, void *context);
+
+/****f* silcutil/SilcScheduleAPI/silc_schedule_signal_call
+ *
+ * SYNOPSIS
+ *
+ *    void silc_schedule_signal_call(SilcSchedule schedule, 
+ *                                   SilcUInt32 signal);
+ *
+ * DESCRIPTION
+ *
+ *    Mark the `signal' to be called later.  Every signal that has been
+ *    registered by silc_schedule_signal_register is delivered by calling
+ *    this function.  When signal really occurs, the application is 
+ *    responsible of calling this function in the signal handler.  After
+ *    signal is over the scheduler will then safely deliver the callback
+ *    that was given to silc_schedule_signal_register function.
+ *
+ ***/
+void silc_schedule_signal_call(SilcSchedule schedule, SilcUInt32 signal);
+
 #endif