c7a8697edce282a0c399c672896b88eb90d3e3c2
[silc.git] / lib / silcutil / silcschedule.h
1 /*
2   
3   silcschedule.h
4  
5   COPYRIGHT
6  
7   Author: Pekka Riikonen <priikone@silcnet.org>
8  
9   Copyright (C) 1998 - 2001 Pekka Riikonen
10  
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2 of the License, or
14   (at your option) any later version.
15  
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20
21 */
22  
23 /****h* silcutil/SILC Schedule Interface
24  *
25  * DESCRIPTION
26  *
27  * The SILC Scheduler is the heart of any application. The scheduler provides
28  * the application's main loop that can handle incoming data, outgoing data,
29  * timeouts and dispatch different kind of tasks.
30  *
31  * The SILC Scheduler supports file descriptor based tasks, timeout tasks
32  * and generic tasks. File descriptor tasks are tasks that perform some 
33  * operation over the specified file descriptor. These include network 
34  * connections, for example. The timeout tasks are timeouts that are executed
35  * after the specified timeout has elapsed. The generic tasks are tasks that
36  * apply to all registered file descriptors thus providing one task that
37  * applies to many independent connections.
38  *
39  * The SILC Scheduler is designed to be the sole main loop of the application
40  * so that the application does not need any other main loop.  However,
41  * SILC Scheduler does support running the scheduler only once, so that the
42  * scheduler does not block, and thus providing a possiblity that some
43  * external main loop is run over the SILC Scheduler. However, these 
44  * applications are considered to be special cases.
45  *
46  * Typical application first initializes the scheduler and then registers
47  * the very first tasks to the scheduler and then run the scheduler.  After
48  * the scheduler's run function returns the application is considered to be 
49  * ended.
50  *
51  * On WIN32 systems the SILC Scheduler is too designed to work as the main
52  * loop of the GUI application. It can handle all Windows messages and
53  * it dispatches them from the scheduler, and thus makes it possible to
54  * create GUI applications. The scheduler can also handle all kinds of
55  * WIN32 handles, this includes sockets created by the SILC Net API routines,
56  * WSAEVENT handle objects created by Winsock2 routines and arbitrary 
57  * WIN32 HANDLE objects.
58  *
59  * The SILC Scheduler supports multi-threads as well. The actual scheduler
60  * must be run in single-thread but other threads may register new tasks
61  * and unregister old tasks.  However, it is enforced that the actual
62  * task is always run in the main thread.  The scheduler is context based
63  * which makes it possible to allocate several schedulers for one application.
64  * Since the scheduler must be run in single-thread, a multi-threaded
65  * application could be created by allocating own scheduler for each of the
66  * worker threads.
67  *
68  ***/
69
70 #ifndef SILCSCHEDULE_H
71 #define SILCSCHEDULE_H
72
73 /****s* silcutil/SilcScheduleAPI/SilcSchedule
74  *
75  * NAME
76  * 
77  *    typedef struct SilcScheduleStruct *SilcSchedule;
78  *
79  * DESCRIPTION
80  *
81  *    This context is the actual Scheduler and is allocated by
82  *    the silc_schedule_init funtion.  The context is given as argument
83  *    to all silc_schedule_* functions.  It must be freed by the 
84  *    silc_schedule_uninit function.
85  *
86  ***/
87 typedef struct SilcScheduleStruct *SilcSchedule;
88
89 /****s* silcutil/SilcScheduleAPI/SilcTask
90  *
91  * NAME
92  * 
93  *    typedef struct SilcTaskStruct *SilcTask;
94  *
95  * DESCRIPTION
96  *
97  *    This object represents one task in the scheduler.  It is allocated
98  *    by the silc_schedule_task_add function and freed by one of the
99  *    silc_schedule_task_del* functions.
100  *
101  ***/
102 typedef struct SilcTaskStruct *SilcTask;
103
104 /****d* silcutil/SilcScheduleAPI/SilcTaskType
105  *
106  * NAME
107  * 
108  *    typedef enum { ... } SilcTaskType;
109  *
110  * DESCRIPTION
111  *
112  *    SILC has three types of tasks, non-timeout tasks (tasks that perform
113  *    over file descriptors), timeout tasks and generic tasks (tasks that
114  *    apply to every file descriptor). This type is sent as argument for the 
115  *    task registering function, silc_schedule_task_add.
116  *
117  * SOURCE
118  */
119 typedef enum {
120   /* File descriptor task that performs some event over file descriptors.
121      These tasks are for example network connections. */
122   SILC_TASK_FD           = 0,
123
124   /* Timeout tasks are tasks that are executed after the specified 
125      time has elapsed. After the task is executed the task is removed
126      automatically from the scheduler. It is safe to re-register the
127      task in task callback. It is also safe to unregister a task in
128      the task callback. */
129   SILC_TASK_TIMEOUT,
130
131   /* Generic tasks are non-timeout tasks and they apply to all file 
132      descriptors, except to those that have explicitly registered a 
133      non-timeout task. These tasks are there to make it simpler and faster 
134      to execute common code that applies to all connections. These are,
135      for example, receiving packets from network and sending packets to
136      network. It doesn't make much sense to register a task that receives
137      a packet from network to every connection when you can have one task
138      that applies to all connections. This is what generic tasks are for.
139      Generic tasks are not bound to any specific file descriptor, however,
140      the correct file descriptor must be passed as argument to task
141      registering function. */
142   SILC_TASK_GENERIC,
143 } SilcTaskType;
144 /***/
145
146 /****d* silcutil/SilcScheduleAPI/SilcTaskEvent
147  *
148  * NAME
149  * 
150  *    typedef enum { ... } SilcTaskEvent;
151  *
152  * DESCRIPTION
153  *
154  *    SILC Task event types.  The event type indicates the occurred
155  *    event of the task.  This type will be given as argument to the
156  *    SilcTaskCallback function to indicate the event for the caller.
157  *    The SILC_TASK_READ and SILC_TASK_WRITE may be set by the caller
158  *    of the silc_schedule_set_listen_fd, if the caller needs to control
159  *    the events for the task. The SILC_TASK_EXPIRE is set always only
160  *    by the scheduler when timeout expires for timeout task.  The
161  *    SILC_TASK_INTERRUPT is set for signal callback.
162  *
163  * SOURCE
164  */
165 typedef enum {
166   SILC_TASK_READ         = 0x0001,               /* Reading */
167   SILC_TASK_WRITE        = 0x0002,               /* Writing */
168   SILC_TASK_EXPIRE       = 0x0004,               /* Timeout */
169   SILC_TASK_INTERRUPT    = 0x0008,               /* Signal */
170 } SilcTaskEvent;
171 /***/
172
173 /****d* silcutil/SilcScheduleAPI/SilcTaskPriority
174  *
175  * NAME
176  * 
177  *    typedef enum { ... } SilcTaskPriority;
178  *
179  * DESCRIPTION
180  *
181  *    Task priorities. Tasks may be registered with different priorities.
182  *    This type defines the different task priorities. The priorities
183  *    behaves same for all type of tasks, fd tasks, timeout tasks and
184  *    generic tasks.
185  *
186  * SOURCE
187  */
188 typedef enum {
189   /* Lowest priority. The task is scheduled to run after its timeout
190      has expired only and only when every other task with higher priority 
191      has already been run. For non-timeout tasks this priority behaves
192      same way. Life is not fair for tasks with this priority. */
193   SILC_TASK_PRI_LOW      = 0,
194
195   /* Normal priority that is used mostly in SILC. This is priority that
196      should always be used unless you specificly need some other priority.
197      The scheduler will run this task as soon as its timeout has expired.
198      For non-timeout tasks this priority behaves same way. Tasks are run 
199      in FIFO (First-In-First-Out) order. */
200   SILC_TASK_PRI_NORMAL,
201 } SilcTaskPriority;
202 /***/
203
204 /****f* silcutil/SilcScheduleAPI/SilcTaskCallback
205  *
206  * SYNOPSIS
207  *
208  *    typedef void (*SilcTaskCallback)(SilcSchedule schedule,
209  *                                     void *app_context,
210  *                                     SilcTaskEvent type, SilcUInt32 fd,
211  *                                     void *context);
212  *
213  * DESCRIPTION
214  *
215  *    The task callback function.  This function will be called by the
216  *    scheduler when some event of the task is performed.  For example,
217  *    when data is available from the connection this will be called.
218  *
219  *    The `schedule' is the scheduler context, the `type' is the indicated
220  *    event, the `fd' is the file descriptor of the task and the `context'
221  *    is a caller specified context. If multiple events occurred this
222  *    callback is called separately for all events.  The `app_context'
223  *    is application specific context that was given as argument to the
224  *    silc_schedule_init function.
225  *
226  *    To specify task callback function in the application using the
227  *    SILC_TASK_CALLBACK and SILC_TASK_CALLBACK_GLOBAL macros is
228  *    recommended.
229  *
230  ***/
231 typedef void (*SilcTaskCallback)(SilcSchedule schedule, void *app_context,
232                                  SilcTaskEvent type, SilcUInt32 fd,
233                                  void *context);
234
235 /* Macros */
236
237 /****d* silcutil/SilcScheduleAPI/SILC_ALL_TASKS
238  *
239  * NAME
240  * 
241  *    #define SILC_ALL_TASKS ...
242  *
243  * DESCRIPTION
244  *
245  *    Marks for all tasks in the scheduler. This can be passed to 
246  *    silc_schedule_task_del function to delete all tasks at once.
247  *
248  * SOURCE
249  */
250 #define SILC_ALL_TASKS ((SilcTask)1)
251 /***/
252
253 /****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
254  *
255  * NAME
256  * 
257  *    #define SILC_TASK_CALLBACK ...
258  *
259  * DESCRIPTION
260  *
261  *    Generic macro to define task callback functions. This defines a
262  *    static function with name `func' as a task callback function.
263  *
264  * SOURCE
265  */
266 #define SILC_TASK_CALLBACK(func)                                \
267 static void func(SilcSchedule schedule, void *app_context,      \
268                  SilcTaskEvent type,                            \
269                  SilcUInt32 fd, void *context)
270 /***/
271
272 /****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK_GLOBAL
273  *
274  * NAME
275  * 
276  *    #define SILC_TASK_CALLBACK_GLOBAL ...
277  *
278  * DESCRIPTION
279  *
280  *    Generic macro to define task callback functions. This defines a
281  *    function with name `func' as a task callback function.  This
282  *    differs from SILC_TASK_CALLBACK in that the defined function is
283  *    not static.
284  *
285  * SOURCE
286  */
287 #define SILC_TASK_CALLBACK_GLOBAL(func)                                 \
288 void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type, \
289           SilcUInt32 fd, void *context)
290 /***/
291
292 /* Prototypes */
293
294 /****f* silcutil/SilcScheduleAPI/silc_schedule_init
295  *
296  * SYNOPSIS
297  *
298  *    SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
299  *
300  * DESCRIPTION
301  *
302  *    Initializes the scheduler. This returns the scheduler context that
303  *    is given as argument usually to all silc_schedule_* functions.
304  *    The `max_tasks' indicates the number of maximum tasks that the
305  *    scheduler can handle. The `app_context' is application specific
306  *    context that is delivered to all task callbacks. The caller must
307  *    free that context.  The 'app_context' can be for example the
308  *    application itself.
309  *
310  ***/
311 SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
312
313 /****f* silcutil/SilcScheduleAPI/silc_schedule_uninit
314  *
315  * SYNOPSIS
316  *
317  *    bool silc_schedule_uninit(SilcSchedule schedule);
318  *
319  * DESCRIPTION
320  *
321  *    Uninitializes the scheduler. This is called when the program is ready
322  *    to end. This removes all tasks from the scheduler. Returns FALSE if the
323  *    scheduler could not be uninitialized. This happens when the scheduler
324  *    is still valid and silc_schedule_stop has not been called.
325  *
326  ***/
327 bool silc_schedule_uninit(SilcSchedule schedule);
328
329 /****f* silcutil/SilcScheduleAPI/silc_schedule_reinit
330  *
331  * SYNOPSIS
332  *
333  *    SilcSchedule silc_schedule_reinit(int max_tasks);
334  *
335  * DESCRIPTION
336  *
337  *    This function can be called to enlarge the task handling capabilities
338  *    of the scheduler indicated by `schedule'.  The `max_tasks' must be
339  *    larger than what was set in silc_schedule_init function.  This function
340  *    returns FALSE if it cannot reinit the scheduler.  This function does
341  *    not do anything else except ready the scheduler to handle `max_tasks'
342  *    number of tasks after this function returns.  It is safe to call this
343  *    function at any time, and it is guaranteed that existing tasks remain
344  *    as they are in the scheduler.
345  *
346  ***/
347 bool silc_schedule_reinit(SilcSchedule schedule, int max_tasks);
348
349 /****f* silcutil/SilcScheduleAPI/silc_schedule_stop
350  *
351  * SYNOPSIS
352  *
353  *    void silc_schedule_stop(SilcSchedule schedule);
354  *
355  * DESCRIPTION
356  *
357  *    Stops the scheduler even if it is not supposed to be stopped yet. 
358  *    After calling this, one must call silc_schedule_uninit (after the 
359  *    silc_schedule has returned).  After this is called it is guaranteed
360  *    that next time the scheduler enters the main loop it will be stopped.
361  *    However, untill it enters the main loop it will not detect that
362  *    it is stopped for example if this is called from another thread.
363  *
364  ***/
365 void silc_schedule_stop(SilcSchedule schedule);
366
367 /****f* silcutil/SilcScheduleAPI/silc_schedule
368  *
369  * SYNOPSIS
370  *
371  *    void silc_schedule(SilcSchedule schedule);
372  *
373  * DESCRIPTION
374  *
375  *    The SILC scheduler. This is actually the main routine in SILC programs.
376  *    When this returns the program is to be ended. Before this function can
377  *    be called, one must call silc_schedule_init function.
378  *
379  ***/
380 void silc_schedule(SilcSchedule schedule);
381
382 /****f* silcutil/SilcScheduleAPI/silc_schedule_one
383  *
384  * SYNOPSIS
385  *
386  *    bool silc_schedule_one(SilcSchedule schedule, int block);
387  *
388  * DESCRIPTION
389  *
390  *    Same as the silc_schedule but runs the scheduler only one round
391  *    and then returns.  This function is handy when the SILC scheduler
392  *    is used inside some other external scheduler, for example.  If
393  *    the `timeout_usecs' is non-negative a timeout will be added to the
394  *    scheduler.  The function will not return in this timeout unless
395  *    some other event occurs.
396  *
397  ***/
398 bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
399
400 /****f* silcutil/SilcScheduleAPI/silc_schedule_wakeup
401  *
402  * SYNOPSIS
403  *
404  *    void silc_schedule_wakeup(SilcSchedule schedule);
405  *
406  * DESCRIPTION
407  *
408  *    Wakes up the scheduler. This is used only in multi-threaded
409  *    environments where threads may add new tasks or remove old tasks
410  *    from the scheduler. This is called to wake up the scheduler in the
411  *    main thread so that it detects the changes in the scheduler.
412  *    If threads support is not compiled in this function has no effect.
413  *    Implementation of this function may be platform specific.
414  *
415  ***/
416 void silc_schedule_wakeup(SilcSchedule schedule);
417
418 /****f* silcutil/SilcScheduleAPI/silc_schedule_get_context
419  *
420  * SYNOPSIS
421  *
422  *    void *silc_schedule_get_context(SilcSchedule schedule);
423  *
424  * DESCRIPTION
425  *
426  *    Returns the application specific context that was saved into the
427  *    scheduler in silc_schedule_init function.  The context is also
428  *    returned to application in task callback functions, but this function
429  *    may be used to get it as well if needed.
430  *
431  ***/
432 void *silc_schedule_get_context(SilcSchedule schedule);
433
434 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add
435  *
436  * SYNOPSIS
437  *
438  *    SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
439  *                                    SilcTaskCallback callback, 
440  *                                    void *context, 
441  *                                    long seconds, long useconds, 
442  *                                    SilcTaskType type, 
443  *                                    SilcTaskPriority priority);
444  *
445  * DESCRIPTION
446  *
447  *    Registers a new task to the scheduler. This same function is used
448  *    to register all types of tasks. The `type' argument tells what type
449  *    of the task is. Note that when registering non-timeout tasks one
450  *    should also pass 0 as timeout, as the timeout will be ignored anyway. 
451  *    Also, note, that one cannot register timeout task with 0 timeout.
452  *    There cannot be zero timeouts, passing zero means no timeout is used
453  *    for the task and SILC_TASK_FD is used as default task type in
454  *    this case.
455  *
456  *    The `schedule' is the scheduler context. The `fd' is the file
457  *    descriptor of the task. On WIN32 systems the `fd' is not actual
458  *    file descriptor but some WIN32 event handle. On WIN32 system the `fd'
459  *    may be a socket created by the SILC Net API routines, WSAEVENT object
460  *    created by Winsock2 network routines or arbitrary WIN32 HANDLE object.
461  *    On Unix systems the `fd' is always the real file descriptor.
462  *
463  *    The `callback' is the task callback that will be called when some
464  *    event occurs for this task. The `context' is sent as argument to
465  *    the task `callback' function. For timeout tasks the callback is
466  *    called after the specified timeout has elapsed.
467  *
468  *    If the `type' is SILC_TASK_TIMEOUT then `seconds' and `useconds'
469  *    may be non-zero.  Otherwise they should be zero. The `priority'
470  *    indicates the priority of the task.
471  *
472  *    It is always safe to call this function in any place. New tasks
473  *    may be added also in task callbacks, and in multi-threaded environment
474  *    in other threads as well.
475  *   
476  ***/
477 SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
478                                 SilcTaskCallback callback, void *context, 
479                                 long seconds, long useconds, 
480                                 SilcTaskType type, 
481                                 SilcTaskPriority priority);
482
483 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del
484  *
485  * SYNOPSIS
486  *
487  *    void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
488  *
489  * DESCRIPTION
490  *
491  *    Deletes the `task' from the scheduler indicated by the `schedule'.
492  *    After deleting the task it is guaranteed that the task callback
493  *    will not be called. If the `task' is SILC_ALL_TASKS then all
494  *    tasks is removed from the scheduler.
495  *
496  *    It is safe to call this function in any place. Tasks may be removed
497  *    in task callbacks (including in the task's own task callback) and
498  *    in multi-threaded environment in other threads as well.
499  *
500  ***/
501 void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
502
503 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_fd
504  *
505  * SYNOPSIS
506  *
507  *    void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd);
508  *
509  * DESCRIPTION
510  *
511  *    Deletes a task from the scheduler by the specified `fd'.
512  *
513  *    It is safe to call this function in any place. Tasks may be removed
514  *    in task callbacks (including in the task's own task callback) and
515  *    in multi-threaded environment in other threads as well.
516  *
517  *    Note that generic tasks cannot be deleted using this function
518  *    since generic tasks does not match any specific fd.
519  *
520  ***/
521 void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd);
522
523 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_callback
524  *
525  * SYNOPSIS
526  *
527  *    void silc_schedule_task_del_by_callback(SilcSchedule schedule,
528  *                                            SilcTaskCallback callback);
529  *
530  * DESCRIPTION
531  *
532  *    Deletes a task from the scheduler by the specified `callback' task
533  *    callback function.
534  *
535  *    It is safe to call this function in any place. Tasks may be removed
536  *    in task callbacks (including in the task's own task callback) and
537  *    in multi-threaded environment in other threads as well.
538  *
539  ***/
540 void silc_schedule_task_del_by_callback(SilcSchedule schedule,
541                                         SilcTaskCallback callback);
542
543 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_context
544  *
545  * SYNOPSIS
546  *
547  *    void silc_schedule_task_del_by_context(SilcSchedule schedule, 
548  *                                           void *context);
549  *
550  * DESCRIPTION
551  *
552  *    Deletes a task from the scheduler by the specified `context'.
553  *
554  *    It is safe to call this function in any place. Tasks may be removed
555  *    in task callbacks (including in the task's own task callback) and
556  *    in multi-threaded environment in other threads as well.
557  *
558  ***/
559 void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
560
561 /****f* silcutil/SilcScheduleAPI/silc_schedule_set_listen_fd
562  *
563  * SYNOPSIS
564  *
565  *    void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
566  *                                     SilcTaskEvent mask, bool send_events);
567  *
568  * DESCRIPTION
569  *
570  *    Sets a file descriptor `fd' to be listened by the scheduler for
571  *    `mask' events.  To tell scheduler not to listen anymore for this
572  *    file descriptor call the silc_schedule_unset_listen_fd function.
573  *    When new task is created with silc_schedule_task_add the event
574  *    for the task's fd is initially set to SILC_TASK_READ. If you need
575  *    to control the task's fd's events you must call this function
576  *    whenever you need to change the events. This can be called multiple
577  *    times to change the events.
578  *
579  *    If the `send_events' is TRUE then this function sends the events
580  *    in `mask' to the application.  If FALSE then they are sent only
581  *    after the event occurs in reality.  In normal cases the `send_events'
582  *    is set to FALSE.
583  *
584  ***/
585 void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
586                                  SilcTaskEvent mask, bool send_events);
587
588 /****f* silcutil/SilcScheduleAPI/silc_schedule_unset_listen_fd
589  *
590  * SYNOPSIS
591  *
592  *    void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd);
593  *
594  * DESCRIPTION
595  *
596  *    Tells the scheduler not to listen anymore for the specified
597  *    file descriptor `fd'. No events will be detected for the `fd'
598  *    after calling this function.
599  *
600  ***/
601 void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd);
602
603 /****f* silcutil/SilcScheduleAPI/silc_schedule_signal_register
604  *
605  * SYNOPSIS
606  *
607  *    void silc_schedule_signal_register(SilcSchedule schedule, 
608  *                                       SilcUInt32 signal,
609  *                                       SilcTaskCallback callback,
610  *                                       void *context);
611  *
612  * DESCRIPTION
613  *
614  *    Register signal indicated by `signal' to the scheduler.  Application
615  *    should register all signals it is going to use to the scheduler.
616  *    The `callback' with `context' will be called after the application
617  *    has called silc_schedule_signal_call function in the real signal 
618  *    callback.  Application is responsible of calling that, and the 
619  *    signal system will not work without calling silc_schedule_signal_call
620  *    function.  The specified `signal' value will be also delivered to
621  *    the `callback' as the fd-argument.  The event type in the callback
622  *    will be SILC_TASK_INTERRUPT.  It is safe to use any SILC routines
623  *    in the `callback' since it is actually called after the signal really
624  *    happened.
625  *
626  *    On platform that does not support signals calling this function has 
627  *    no effect.
628  *
629  * EXAMPLE
630  *
631  *    Typical signal usage case on Unix systems:
632  *
633  *    struct sigaction sa;
634  *    sa.sa_handler = signal_handler;
635  *    sigaction(SIGHUP, &sa, NULL);
636  *    sigaction(SIGINT, &sa, NULL);
637  *    silc_schedule_signal_register(schedule, SIGHUP, hup_signal, context);
638  *    silc_schedule_signal_register(schedule, SIGINT, int_signal, context);
639  *
640  *    static void signal_handler(int sig)
641  *    {
642  *      silc_schedule_signal_call(schedule, sig);
643  *    }
644  *
645  *    The `signal_handler' can be used as generic signal callback in the
646  *    application that merely calls silc_schedule_signal_call, which then
647  *    eventually will deliver for example the `hup_signal' callback.  The 
648  *    same `signal_handler' can be used with all signals.
649  *
650  ***/
651 void silc_schedule_signal_register(SilcSchedule schedule, SilcUInt32 signal,
652                                    SilcTaskCallback callback, void *context);
653
654 /****f* silcutil/SilcScheduleAPI/silc_schedule_signal_unregister
655  *
656  * SYNOPSIS
657  *
658  *    void silc_schedule_signal_unregister(SilcSchedule schedule, 
659  *                                         SilcUInt32 signal,
660  *                                         SilcTaskCallback callback,
661  *                                         void *context);
662  *
663  * DESCRIPTION
664  *
665  *    Unregister a signal indicated by `signal' from the scheduler.  On
666  *    platform that does not support signals calling this function has no
667  *    effect.
668  *
669  ***/
670 void silc_schedule_signal_unregister(SilcSchedule schedule, SilcUInt32 signal,
671                                      SilcTaskCallback callback, void *context);
672
673 /****f* silcutil/SilcScheduleAPI/silc_schedule_signal_call
674  *
675  * SYNOPSIS
676  *
677  *    void silc_schedule_signal_call(SilcSchedule schedule, 
678  *                                   SilcUInt32 signal);
679  *
680  * DESCRIPTION
681  *
682  *    Mark the `signal' to be called later.  Every signal that has been
683  *    registered by silc_schedule_signal_register is delivered by calling
684  *    this function.  When signal really occurs, the application is 
685  *    responsible of calling this function in the signal handler.  After
686  *    signal is over the scheduler will then safely deliver the callback
687  *    that was given to silc_schedule_signal_register function.
688  *
689  ***/
690 void silc_schedule_signal_call(SilcSchedule schedule, SilcUInt32 signal);
691
692 #endif