Symbian compilation fixes.
[silc.git] / lib / silcutil / silcschedule.h
index 4574cd8c51b12358ddca8e45a84af9e6992b8757..4dc15c50c928335fd84aec73e45c103e9031baac 100644 (file)
@@ -1,26 +1,23 @@
 /*
-  
+
   silcschedule.h
-  COPYRIGHT
+
   Author: Pekka Riikonen <priikone@silcnet.org>
-  Copyright (C) 1998 - 2001 Pekka Riikonen
+
+  Copyright (C) 1998 - 2006 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
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
 */
-/****h* silcutil/silcschedule.h
+
+/****h* silcutil/SILC Schedule Interface
  *
  * DESCRIPTION
  *
  * the application's main loop that can handle incoming data, outgoing data,
  * timeouts and dispatch different kind of tasks.
  *
- * The SILC Scheduler supports file descriptor based tasks, timeout tasks
- * and generic tasks. File descriptor tasks are tasks that perform some 
- * operation over the specified file descriptor. These include network 
- * connections, for example. The timeout tasks are timeouts that are executed
- * after the specified timeout has elapsed. The generic tasks are tasks that
- * apply to all registered file descriptors thus providing one task that
- * applies to many independent connections.
+ * The SILC Scheduler supports file descriptor based tasks and timeout tasks.
+ * File descriptor tasks are tasks that perform some operation over the
+ * specified file descriptor. These include network connections, for example.
+ * The timeout tasks are timeouts that are executed after the specified
+ * timeout has elapsed.
  *
  * The SILC Scheduler is designed to be the sole main loop of the application
  * so that the application does not need any other main loop.  However,
  * SILC Scheduler does support running the scheduler only once, so that the
  * scheduler does not block, and thus providing a possiblity that some
- * external main loop is run over the SILC Scheduler. However, these 
- * applications are considered to be special cases.
+ * external main loop is run over the SILC Scheduler.
  *
  * Typical application first initializes the scheduler and then registers
  * the very first tasks to the scheduler and then run the scheduler.  After
- * the scheduler's run function returns the application is considered to be 
+ * the scheduler's run function returns the application is considered to be
  * ended.
  *
  * On WIN32 systems the SILC Scheduler is too designed to work as the main
@@ -53,7 +47,7 @@
  * 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 created by Winsock2 routines and arbitrary 
+ * WSAEVENT handle objects created by Winsock2 routines and arbitrary
  * WIN32 HANDLE objects.
  *
  * The SILC Scheduler supports multi-threads as well. The actual scheduler
 /****s* silcutil/SilcScheduleAPI/SilcSchedule
  *
  * NAME
- * 
+ *
  *    typedef struct SilcScheduleStruct *SilcSchedule;
  *
  * DESCRIPTION
  *
  *    This context is the actual Scheduler and is allocated by
  *    the silc_schedule_init funtion.  The context is given as argument
- *    to all silc_schedule_* functions.  It must be freed by the 
+ *    to all silc_schedule_* functions.  It must be freed by the
  *    silc_schedule_uninit function.
  *
  ***/
@@ -89,7 +83,7 @@ typedef struct SilcScheduleStruct *SilcSchedule;
 /****s* silcutil/SilcScheduleAPI/SilcTask
  *
  * NAME
- * 
+ *
  *    typedef struct SilcTaskStruct *SilcTask;
  *
  * DESCRIPTION
@@ -104,49 +98,40 @@ typedef struct SilcTaskStruct *SilcTask;
 /****d* silcutil/SilcScheduleAPI/SilcTaskType
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcTaskType;
  *
  * DESCRIPTION
  *
- *    SILC has three types of tasks, non-timeout tasks (tasks that perform
- *    over file descriptors), timeout tasks and generic tasks (tasks that
- *    apply to every file descriptor). This type is sent as argument for the 
- *    task registering function, silc_schedule_task_add.
+ *    SILC has two types of tasks, non-timeout tasks (tasks that perform
+ *    over file descriptors), and timeout tasks.  This type is sent as
+ *    argument for the task registering function, silc_schedule_task_add.
  *
  * SOURCE
  */
 typedef enum {
   /* File descriptor task that performs some event over file descriptors.
      These tasks are for example network connections. */
-  SILC_TASK_FD,
-  
-  /* Timeout tasks are tasks that are executed after the specified 
+  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
      task in task callback. It is also safe to unregister a task in
      the task callback. */
   SILC_TASK_TIMEOUT,
 
-  /* Generic tasks are non-timeout tasks and they apply to all file 
-     descriptors, except to those that have explicitly registered a 
-     non-timeout task. These tasks are there to make it simpler and faster 
-     to execute common code that applies to all connections. These are,
-     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.
-     Generic tasks are not bound to any specific file descriptor, however,
-     the correct file descriptor must be passed as argument to task
-     registering function. */
-  SILC_TASK_GENERIC,
+  /* Platform specific process signal task.  On Unix systems this is one of
+     the signals described in signal(7).  On other platforms this may not
+     be available at all.  Only one callback per signal may be added. */
+  SILC_TASK_SIGNAL
 } SilcTaskType;
 /***/
 
 /****d* silcutil/SilcScheduleAPI/SilcTaskEvent
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcTaskEvent;
  *
  * DESCRIPTION
@@ -157,54 +142,26 @@ 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;
 /***/
 
-/****d* silcutil/SilcScheduleAPI/SilcTaskPriority
- *
- * NAME
- * 
- *    typedef enum { ... } SilcTaskPriority
- *
- * DESCRIPTION
- *
- *    Task priorities. Tasks may be registered with different priorities.
- *    This type defines the different task priorities. The priorities
- *    behaves same for all type of tasks, fd tasks, timeout tasks and
- *    generic tasks.
- *
- * SOURCE
- */
-typedef enum {
-  /* Lowest priority. The task is scheduled to run after its timeout
-     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,
-
-  /* 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 
-     in FIFO (First-In-First-Out) order. */
-  SILC_TASK_PRI_NORMAL,
-} 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
@@ -216,27 +173,30 @@ 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.  If the task is timeout task then `fd'
+ *    is zero (0).
  *
  *    To specify task callback function in the application using the
- *    SILC_TASK_CALLBACK and SILC_TASK_CALLBACK_GLOBAL macros is
- *    recommended.
+ *    SILC_TASK_CALLBACK macro 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 */
 
 /****d* silcutil/SilcScheduleAPI/SILC_ALL_TASKS
  *
  * NAME
- * 
+ *
  *    #define SILC_ALL_TASKS ...
  *
  * DESCRIPTION
  *
- *    Marks for all tasks in the scheduler. This can be passed to 
+ *    Marks for all tasks in the scheduler. This can be passed to
  *    silc_schedule_task_del function to delete all tasks at once.
  *
  * SOURCE
@@ -247,7 +207,7 @@ typedef void (*SilcTaskCallback)(SilcSchedule schedule, SilcTaskEvent type,
 /****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
  *
  * NAME
- * 
+ *
  *    #define SILC_TASK_CALLBACK ...
  *
  * DESCRIPTION
@@ -257,29 +217,9 @@ typedef void (*SilcTaskCallback)(SilcSchedule schedule, SilcTaskEvent type,
  *
  * SOURCE
  */
-#define SILC_TASK_CALLBACK(func)                               \
-static void func(SilcSchedule schedule, SilcTaskEvent type,    \
-                uint32 fd, void *context)
-/***/
-
-/****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
- *
- * NAME
- * 
- *    #define SILC_TASK_CALLBACK_GLOBAL ...
- *
- * DESCRIPTION
- *
- *    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.
- *
- * SOURCE
- */
-#define SILC_TASK_CALLBACK_GLOBAL(func)                        \
-void func(SilcSchedule schedule, SilcTaskEvent type,   \
-         uint32 fd, void *context)
+#define SILC_TASK_CALLBACK(func)                                       \
+void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type,        \
+         SilcUInt32 fd, void *context)
 /***/
 
 /* Prototypes */
@@ -288,23 +228,30 @@ 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.
+ *    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.
+ *
+ *    The `max_tasks' is the maximum number of SILC_TASK_FD tasks in the
+ *    scheduler.  Set value to 0 to use default.  Operating system will
+ *    enforce the final limit.  On some operating systems the limit can
+ *    be significantly increased when this function is called in priviliged
+ *    mode (as super user).
  *
  ***/
-SilcSchedule silc_schedule_init(int max_tasks);
+SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_uninit
  *
  * SYNOPSIS
  *
- *    bool silc_schedule_uninit(SilcSchedule schedule);
+ *    SilcBool silc_schedule_uninit(SilcSchedule schedule);
  *
  * DESCRIPTION
  *
@@ -314,7 +261,7 @@ SilcSchedule silc_schedule_init(int max_tasks);
  *    is still valid and silc_schedule_stop has not been called.
  *
  ***/
-bool silc_schedule_uninit(SilcSchedule schedule);
+SilcBool silc_schedule_uninit(SilcSchedule schedule);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_stop
  *
@@ -324,9 +271,12 @@ bool silc_schedule_uninit(SilcSchedule schedule);
  *
  * DESCRIPTION
  *
- *    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).
+ *    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).  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);
@@ -339,10 +289,18 @@ void silc_schedule_stop(SilcSchedule schedule);
  *
  * DESCRIPTION
  *
- *    The SILC scheduler. This is actually the main routine in SILC programs.
+ *    The SILC scheduler. The program will run inside this function.
  *    When this returns the program is to be ended. Before this function can
  *    be called, one must call silc_schedule_init function.
  *
+ * NOTES
+ *
+ *    On Windows this will block the program, but will continue dispatching
+ *    window messages, and thus can be used as the main loop of the program.
+ *
+ *    On Symbian this will return immediately.  On Symbian calling
+ *    silc_schedule is same as calling silc_schedule_one.
+ *
  ***/
 void silc_schedule(SilcSchedule schedule);
 
@@ -350,7 +308,7 @@ void silc_schedule(SilcSchedule schedule);
  *
  * SYNOPSIS
  *
- *    bool silc_schedule_one(SilcSchedule schedule, int block);
+ *    SilcBool silc_schedule_one(SilcSchedule schedule, int block);
  *
  * DESCRIPTION
  *
@@ -361,8 +319,12 @@ void silc_schedule(SilcSchedule schedule);
  *    scheduler.  The function will not return in this timeout unless
  *    some other event occurs.
  *
+ *    Typically this would be called from a timeout or idle task
+ *    periodically (typically from 5-50 ms) to schedule SILC tasks.  In
+ *    this case the `timeout_usecs' is usually 0.
+ *
  ***/
-bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
+SilcBool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_wakeup
  *
@@ -382,54 +344,91 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
  ***/
 void silc_schedule_wakeup(SilcSchedule schedule);
 
-/****f* silcutil/SilcScheduleAPI/silc_schedule_task_add
+/****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_fd
  *
  * SYNOPSIS
  *
- *    SilcTask silc_schedule_task_add(SilcSchedule schedule, uint32 fd,
- *                                    SilcTaskCallback callback, 
- *                                    void *context, 
- *                                    long seconds, long useconds, 
- *                                    SilcTaskType type, 
- *                                    SilcTaskPriority priority);
+ *    SilcTask
+ *    silc_schedule_task_add_fd(SilcSchedule schedule, SilcUInt32 fd,
+ *                              SilcTaskCallback callback, void *context);
  *
  * DESCRIPTION
  *
- *    Registers a new task to the scheduler. This same function is used
- *    to register all types of tasks. The `type' argument tells what type
- *    of the task is. Note that when registering non-timeout tasks one
- *    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 is used as default task type in
- *    this case.
- *
- *    The `schedule' is the scheduler context. The `fd' is the file
- *    descriptor of the task. On WIN32 systems the `fd' is not actual
- *    file descriptor but some WIN32 event handle. On WIN32 system the `fd'
- *    may be a socket created by the SILC Net API routines, WSAEVENT object
- *    created by Winsock2 network routines or arbitrary WIN32 HANDLE object.
- *    On Unix systems the `fd' is always the real file descriptor.
- *
- *    The `callback' is the task callback that will be called when some
- *    event occurs for this task. The `context' is sent as argument to
- *    the task `callback' function. For timeout tasks the callback is
- *    called after the specified timeout has elapsed.
- *
- *    If the `type' is SILC_TASK_TIMEOUT then `seconds' and `useconds'
- *    may be non-zero.  Otherwise they should be zero. The `priority'
- *    indicates the priority of the task.
- *
- *    It is always safe to call this function in any place. New tasks
- *    may be added also in task callbacks, and in multi-threaded environment
- *    in other threads as well.
- *   
+ *    Add file descriptor task to scheduler.  The `fd' may be either real
+ *    file descriptor, socket or on some platforms an opaque file descriptor
+ *    handle.  To receive events for the file descriptor set the correct
+ *    request events with silc_schedule_set_listen_fd function.
+ *
  ***/
-SilcTask silc_schedule_task_add(SilcSchedule schedule, uint32 fd,
-                               SilcTaskCallback callback, void *context, 
-                               long seconds, long useconds, 
-                               SilcTaskType type, 
-                               SilcTaskPriority priority);
+#define silc_schedule_task_add_fd(schedule, fd, callback, context)     \
+  silc_schedule_task_add(schedule, fd, callback, context, 0, 0,        SILC_TASK_FD)
+
+/****f* silcutil/SilcScheduleAPI/silc_schedule_task_add_timeout
+ *
+ * SYNOPSIS
+ *
+ *    SilcTask
+ *    silc_schedule_task_add_timeout(SilcSchedule schedule,
+ *                                   SilcTaskCallback callback, void *context,
+ *                                   long seconds, long useconds);
+ *
+ * DESCRIPTION
+ *
+ *    Add timeout task to scheduler.  The `callback' will be called once
+ *    the specified timeout has elapsed.  The task will be removed from the
+ *    scheduler automatically once the task expires.  The event returned
+ *    to the `callback' is SILC_TASK_EXPIRE.  The task added with zero (0)
+ *    timeout will be executed immediately next time tasks are scheduled.
+ *
+ ***/
+#define silc_schedule_task_add_timeout(schedule, callback, context, s, u) \
+  silc_schedule_task_add(schedule, 0, callback, context, s, u,         \
+                         SILC_TASK_TIMEOUT)
+
+/****f* silcutil/SilcScheduleAPI/silc_schedule_task_add_signal
+ *
+ * SYNOPSIS
+ *
+ *    SilcTask
+ *    silc_schedule_task_add_signal(SilcSchedule schedule, int signal,
+ *                                  SilcTaskCallback callback, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Add platform specific process signal handler to scheduler.  On Unix
+ *    systems the `signal' is one of the signal specified in signal(7).  On
+ *    other platforms this function may not be available at all, and has no
+ *    effect when called.  The event delivered to the `callback' is
+ *    SILC_TASK_INTERRUPT.
+ *
+ * NOTES
+ *
+ *    One signal may be registered only one callback.  Adding second callback
+ *    for signal that already has one will fail.
+ *
+ *    This function always returns NULL.  To remove signal from scheduler by
+ *    the signal call silc_schedule_task_del_by_fd.
+ *
+ ***/
+#define silc_schedule_task_add_signal(schedule, sig, callback, context) \
+  silc_schedule_task_add(schedule, sig, callback, context, 0, 0,       \
+                        SILC_TASK_SIGNAL)
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del
  *
@@ -455,7 +454,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
  *
@@ -465,11 +464,8 @@ 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
  *
@@ -495,7 +491,7 @@ void silc_schedule_task_del_by_callback(SilcSchedule schedule,
  *
  * SYNOPSIS
  *
- *    void silc_schedule_task_del_by_context(SilcSchedule schedule, 
+ *    void silc_schedule_task_del_by_context(SilcSchedule schedule,
  *                                           void *context);
  *
  * DESCRIPTION
@@ -509,12 +505,34 @@ void silc_schedule_task_del_by_callback(SilcSchedule schedule,
  ***/
 void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
 
+/****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_all
+ *
+ * SYNOPSIS
+ *
+ *    void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
+ *                                       SilcTaskCallback callback,
+ *                                       void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Deletes a task from the scheduler by the specified `fd', `callback'
+ *    and `context'.
+ *
+ *    It is safe to call this function in any place. Tasks may be removed
+ *    in task callbacks (including in the task's own task callback) and
+ *    in multi-threaded environment in other threads as well.
+ *
+ ***/
+void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
+                                  SilcTaskCallback callback, void *context);
+
 /****f* silcutil/SilcScheduleAPI/silc_schedule_set_listen_fd
  *
  * 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,
+ *                                     SilcBool send_events);
  *
  * DESCRIPTION
  *
@@ -527,15 +545,36 @@ 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, SilcBool send_events);
+
+/****f* silcutil/SilcScheduleAPI/silc_schedule_get_fd_events
+ *
+ * SYNOPSIS
+ *
+ *    SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
+ *                                              SilcUInt32 fd);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the file descriptor `fd' current requested events mask,
+ *    or 0 on error.
+ *
  ***/
-void silc_schedule_set_listen_fd(SilcSchedule schedule, uint32 fd,
-                                SilcTaskEvent mask);
+SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
+                                         SilcUInt32 fd);
 
 /****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
  *
@@ -544,6 +583,8 @@ 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);
+
+#include "silcschedule_i.h"
 
 #endif