Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / silcschedule.h
index 8866f700a1c2a7e177d69e99d93ac1719d0e6806..be24c41a20c8df5864d258a288381264dffe3688 100644 (file)
@@ -1,26 +1,25 @@
-/****h* silcutil/silcschedule.h
- *
- * NAME
- *
- * silcschedule.h
- *
- * COPYRIGHT
- *
- * Author: Pekka Riikonen <priikone@silcnet.org>
- *
- * Copyright (C) 1998 - 2001 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+/*
+  
+  silcschedule.h
+  Author: Pekka Riikonen <priikone@silcnet.org>
+  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; 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
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+/****h* silcutil/SILC Schedule Interface
  *
# DESCRIPTION
* DESCRIPTION
  *
  * The SILC Scheduler is the heart of any application. The scheduler provides
  * the application's main loop that can handle incoming data, outgoing data,
  * the scheduler's run function returns the application is considered to be 
  * ended.
  *
- * On WIN32 systems the SILC Scheduler is also designed to work as the main
+ * On WIN32 systems the SILC Scheduler is too designed to work as the main
  * loop of the GUI application. It can handle all Windows messages and
- * it dispatches them from the scheduler and thus makes it possible to
+ * it dispatches them from the scheduler, and thus makes it possible to
  * create GUI applications. The scheduler can also handle all kinds of
  * WIN32 handles, this includes sockets created by the SILC Net API routines,
- * WSAEVENT handle objects and arbitrary WIN32 HANDLE objects.
+ * WSAEVENT handle objects created by Winsock2 routines and arbitrary 
+ * WIN32 HANDLE objects.
  *
  * The SILC Scheduler supports multi-threads as well. The actual scheduler
  * must be run in single-thread but other threads may register new tasks
@@ -62,7 +62,7 @@
  * application could be created by allocating own scheduler for each of the
  * worker threads.
  *
- */
+ ***/
 
 #ifndef SILCSCHEDULE_H
 #define SILCSCHEDULE_H
@@ -116,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
@@ -132,7 +132,7 @@ typedef enum {
      for example, receiving packets from network and sending packets to
      network. It doesn't make much sense to register a task that receives
      a packet from network to every connection when you can have one task
-     that applies to all connections. This is what generic tasks are for-
+     that applies to all connections. This is what generic tasks are for.
      Generic tasks are not bound to any specific file descriptor, however,
      the correct file descriptor must be passed as argument to task
      registering function. */
@@ -152,16 +152,18 @@ typedef enum {
  *    event of the task.  This type will be given as argument to the
  *    SilcTaskCallback function to indicate the event for the caller.
  *    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_TIMEOUT is set always only
- *    by the scheduler when timeout for timeout task occurs.
+ *    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.  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;
 /***/
 
@@ -169,7 +171,7 @@ typedef enum {
  *
  * NAME
  * 
- *    typedef enum { ... } SilcTaskPriority
+ *    typedef enum { ... } SilcTaskPriority;
  *
  * DESCRIPTION
  *
@@ -185,9 +187,9 @@ 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
+  /* Normal priority that is used mostly in SILC. This is priority that
      should always be used unless you specificly need some other priority.
      The scheduler will run this task as soon as its timeout has expired.
      For non-timeout tasks this priority behaves same way. Tasks are run 
@@ -196,12 +198,13 @@ typedef enum {
 } SilcTaskPriority;
 /***/
 
-/****f* silcutil/SilcScheduleAPI/silc_schedule_init
+/****f* silcutil/SilcScheduleAPI/SilcTaskCallback
  *
  * SYNOPSIS
  *
- *    typedef void (*SilcTaskCallback)(SilcSchedule schedule, 
- *                                     SilcTaskEvent type, uint32 fd, 
+ *    typedef void (*SilcTaskCallback)(SilcSchedule schedule,
+ *                                     void *app_context,
+ *                                     SilcTaskEvent type, SilcUInt32 fd,
  *                                     void *context);
  *
  * DESCRIPTION
@@ -213,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
- *    call 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,
-                                uint32 fd, void *context);
+typedef void (*SilcTaskCallback)(SilcSchedule schedule, void *app_context,
+                                SilcTaskEvent type, SilcUInt32 fd,
+                                void *context);
 
 /* Macros */
 
@@ -255,11 +261,12 @@ typedef void (*SilcTaskCallback)(SilcSchedule schedule, SilcTaskEvent type,
  * SOURCE
  */
 #define SILC_TASK_CALLBACK(func)                               \
-static void func(SilcSchedule schedule, SilcTaskEvent type,    \
-                uint32 fd, void *context)
+static void func(SilcSchedule schedule, void *app_context,     \
+                SilcTaskEvent type,                            \
+                SilcUInt32 fd, void *context)
 /***/
 
-/****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
+/****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK_GLOBAL
  *
  * NAME
  * 
@@ -270,13 +277,13 @@ static void func(SilcSchedule schedule, SilcTaskEvent type,       \
  *    Generic macro to define task callback functions. This defines a
  *    function with name `func' as a task callback function.  This
  *    differs from SILC_TASK_CALLBACK in that the defined function is
- *    not static function.
+ *    not static.
  *
  * SOURCE
  */
-#define SILC_TASK_CALLBACK_GLOBAL(func)                        \
-void func(SilcSchedule schedule, SilcTaskEvent type,   \
-         uint32 fd, void *context)
+#define SILC_TASK_CALLBACK_GLOBAL(func)                                        \
+void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type,        \
+         SilcUInt32 fd, void *context)
 /***/
 
 /* Prototypes */
@@ -285,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 arugment usually to all silc_schedule_* functions.
+ *    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
  *
@@ -305,7 +315,7 @@ SilcSchedule silc_schedule_init(int max_tasks);
  *
  * DESCRIPTION
  *
- *    Uninitializes the schedule. This is called when the program is ready
+ *    Uninitializes the scheduler. This is called when the program is ready
  *    to end. This removes all tasks from the scheduler. Returns FALSE if the
  *    scheduler could not be uninitialized. This happens when the scheduler
  *    is still valid and silc_schedule_stop has not been called.
@@ -313,6 +323,26 @@ SilcSchedule silc_schedule_init(int max_tasks);
  ***/
 bool silc_schedule_uninit(SilcSchedule schedule);
 
+/****f* silcutil/SilcScheduleAPI/silc_schedule_reinit
+ *
+ * SYNOPSIS
+ *
+ *    SilcSchedule silc_schedule_reinit(int max_tasks);
+ *
+ * DESCRIPTION
+ *
+ *    This function can be called to enlarge the task handling capabilities
+ *    of the scheduler indicated by `schedule'.  The `max_tasks' must be
+ *    larger than what was set in silc_schedule_init function.  This function
+ *    returns FALSE if it cannot reinit the scheduler.  This function does
+ *    not do anything else except ready the scheduler to handle `max_tasks'
+ *    number of tasks after this function returns.  It is safe to call this
+ *    function at any time, and it is guaranteed that existing tasks remain
+ *    as they are in the scheduler.
+ *
+ ***/
+bool silc_schedule_reinit(SilcSchedule schedule, int max_tasks);
+
 /****f* silcutil/SilcScheduleAPI/silc_schedule_stop
  *
  * SYNOPSIS
@@ -323,7 +353,10 @@ bool silc_schedule_uninit(SilcSchedule schedule);
  *
  *    Stops the scheduler even if it is not supposed to be stopped yet. 
  *    After calling this, one must call silc_schedule_uninit (after the 
- *    silc_schedule has returned).
+ *    silc_schedule has returned).  After this is called it is guaranteed
+ *    that next time the scheduler enters the main loop it will be stopped.
+ *    However, untill it enters the main loop it will not detect that
+ *    it is stopped for example if this is called from another thread.
  *
  ***/
 void silc_schedule_stop(SilcSchedule schedule);
@@ -343,7 +376,7 @@ void silc_schedule_stop(SilcSchedule schedule);
  ***/
 void silc_schedule(SilcSchedule schedule);
 
-/****f* silcutil/SilcScheduleAPI/silc_schedule
+/****f* silcutil/SilcScheduleAPI/silc_schedule_one
  *
  * SYNOPSIS
  *
@@ -379,11 +412,27 @@ 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
  *
- *    SilcTask silc_schedule_task_add(SilcSchedule schedule, uint32 fd,
+ *    SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
  *                                    SilcTaskCallback callback, 
  *                                    void *context, 
  *                                    long seconds, long useconds, 
@@ -398,7 +447,7 @@ void silc_schedule_wakeup(SilcSchedule schedule);
  *    should also pass 0 as timeout, as the timeout will be ignored anyway. 
  *    Also, note, that one cannot register timeout task with 0 timeout.
  *    There cannot be zero timeouts, passing zero means no timeout is used
- *    for the task and SILC_TASK_FD_TASK is used as default task type in
+ *    for the task and SILC_TASK_FD is used as default task type in
  *    this case.
  *
  *    The `schedule' is the scheduler context. The `fd' is the file
@@ -422,7 +471,7 @@ void silc_schedule_wakeup(SilcSchedule schedule);
  *    in other threads as well.
  *   
  ***/
-SilcTask silc_schedule_task_add(SilcSchedule schedule, uint32 fd,
+SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
                                SilcTaskCallback callback, void *context, 
                                long seconds, long useconds, 
                                SilcTaskType type, 
@@ -452,7 +501,7 @@ void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
  *
  * SYNOPSIS
  *
- *    void silc_schedule_task_del_by_fd(SilcSchedule schedule, uint32 fd);
+ *    void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd);
  *
  * DESCRIPTION
  *
@@ -462,8 +511,11 @@ void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
  *    in task callbacks (including in the task's own task callback) and
  *    in multi-threaded environment in other threads as well.
  *
+ *    Note that generic tasks cannot be deleted using this function
+ *    since generic tasks does not match any specific fd.
+ *
  ***/
-void silc_schedule_task_del_by_fd(SilcSchedule schedule, uint32 fd);
+void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_callback
  *
@@ -507,8 +559,8 @@ void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
  *
  * SYNOPSIS
  *
- *    void silc_schedule_set_listen_fd(SilcSchedule schedule, uint32 fd,
- *                                     SilcTaskEvent mask);
+ *    void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+ *                                     SilcTaskEvent mask, bool send_events);
  *
  * DESCRIPTION
  *
@@ -521,15 +573,20 @@ 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, uint32 fd,
-                                SilcTaskEvent mask);
+void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+                                SilcTaskEvent mask, bool send_events);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_unset_listen_fd
  *
  * SYNOPSIS
  *
- *    void silc_schedule_unset_listen_fd(SilcSchedule schedule, uint32 fd);
+ *    void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd);
  *
  * DESCRIPTION
  *
@@ -538,6 +595,95 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, uint32 fd,
  *    after calling this function.
  *
  ***/
-void silc_schedule_unset_listen_fd(SilcSchedule schedule, uint32 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