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