Removed signal registering and unregistering and added
[crypto.git] / lib / silcutil / silcschedule.h
1 /*
2
3   silcschedule.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1998 - 2006 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 and timeout tasks.
29  * File descriptor tasks are tasks that perform some operation over the
30  * specified file descriptor. These include network connections, for example.
31  * The timeout tasks are timeouts that are executed after the specified
32  * timeout has elapsed.
33  *
34  * The SILC Scheduler is designed to be the sole main loop of the application
35  * so that the application does not need any other main loop.  However,
36  * SILC Scheduler does support running the scheduler only once, so that the
37  * scheduler does not block, and thus providing a possiblity that some
38  * external main loop is run over the SILC Scheduler.
39  *
40  * Typical application first initializes the scheduler and then registers
41  * the very first tasks to the scheduler and then run the scheduler.  After
42  * the scheduler's run function returns the application is considered to be
43  * ended.
44  *
45  * On WIN32 systems the SILC Scheduler is too designed to work as the main
46  * loop of the GUI application. It can handle all Windows messages and
47  * it dispatches them from the scheduler, and thus makes it possible to
48  * create GUI applications. The scheduler can also handle all kinds of
49  * WIN32 handles, this includes sockets created by the SILC Net API routines,
50  * WSAEVENT handle objects created by Winsock2 routines and arbitrary
51  * WIN32 HANDLE objects.
52  *
53  * The SILC Scheduler supports multi-threads as well. The actual scheduler
54  * must be run in single-thread but other threads may register new tasks
55  * and unregister old tasks.  However, it is enforced that the actual
56  * task is always run in the main thread.  The scheduler is context based
57  * which makes it possible to allocate several schedulers for one application.
58  * Since the scheduler must be run in single-thread, a multi-threaded
59  * application could be created by allocating own scheduler for each of the
60  * worker threads.
61  *
62  ***/
63
64 #ifndef SILCSCHEDULE_H
65 #define SILCSCHEDULE_H
66
67 /****s* silcutil/SilcScheduleAPI/SilcSchedule
68  *
69  * NAME
70  *
71  *    typedef struct SilcScheduleStruct *SilcSchedule;
72  *
73  * DESCRIPTION
74  *
75  *    This context is the actual Scheduler and is allocated by
76  *    the silc_schedule_init funtion.  The context is given as argument
77  *    to all silc_schedule_* functions.  It must be freed by the
78  *    silc_schedule_uninit function.
79  *
80  ***/
81 typedef struct SilcScheduleStruct *SilcSchedule;
82
83 /****s* silcutil/SilcScheduleAPI/SilcTask
84  *
85  * NAME
86  *
87  *    typedef struct SilcTaskStruct *SilcTask;
88  *
89  * DESCRIPTION
90  *
91  *    This object represents one task in the scheduler.  It is allocated
92  *    by the silc_schedule_task_add function and freed by one of the
93  *    silc_schedule_task_del* functions.
94  *
95  ***/
96 typedef struct SilcTaskStruct *SilcTask;
97
98 /****d* silcutil/SilcScheduleAPI/SilcTaskType
99  *
100  * NAME
101  *
102  *    typedef enum { ... } SilcTaskType;
103  *
104  * DESCRIPTION
105  *
106  *    SILC has two types of tasks, non-timeout tasks (tasks that perform
107  *    over file descriptors), and timeout tasks.  This type is sent as
108  *    argument for the task registering function, silc_schedule_task_add.
109  *
110  * SOURCE
111  */
112 typedef enum {
113   /* File descriptor task that performs some event over file descriptors.
114      These tasks are for example network connections. */
115   SILC_TASK_FD           = 0,
116
117   /* Timeout tasks are tasks that are executed after the specified
118      time has elapsed. After the task is executed the task is removed
119      automatically from the scheduler. It is safe to re-register the
120      task in task callback. It is also safe to unregister a task in
121      the task callback. */
122   SILC_TASK_TIMEOUT,
123
124   /* Platform specific process signal task.  On Unix systems this is one of
125      the signals described in signal(7).  On other platforms this may not
126      be available at all.  Only one callback per signal may be added. */
127   SILC_TASK_SIGNAL
128 } SilcTaskType;
129 /***/
130
131 /****d* silcutil/SilcScheduleAPI/SilcTaskEvent
132  *
133  * NAME
134  *
135  *    typedef enum { ... } SilcTaskEvent;
136  *
137  * DESCRIPTION
138  *
139  *    SILC Task event types.  The event type indicates the occurred
140  *    event of the task.  This type will be given as argument to the
141  *    SilcTaskCallback function to indicate the event for the caller.
142  *    The SILC_TASK_READ and SILC_TASK_WRITE may be set by the caller
143  *    of the silc_schedule_set_listen_fd, if the caller needs to control
144  *    the events for the task. The SILC_TASK_EXPIRE is set always only
145  *    by the scheduler when timeout expires for timeout task.  The
146  *    SILC_TASK_INTERRUPT is set for signal callback.
147  *
148  * SOURCE
149  */
150 typedef enum {
151   SILC_TASK_READ         = 0x0001,               /* Reading */
152   SILC_TASK_WRITE        = 0x0002,               /* Writing */
153   SILC_TASK_EXPIRE       = 0x0004,               /* Timeout */
154   SILC_TASK_INTERRUPT    = 0x0008,               /* Signal */
155 } SilcTaskEvent;
156 /***/
157
158 /****f* silcutil/SilcScheduleAPI/SilcTaskCallback
159  *
160  * SYNOPSIS
161  *
162  *    typedef void (*SilcTaskCallback)(SilcSchedule schedule,
163  *                                     void *app_context,
164  *                                     SilcTaskEvent type, SilcUInt32 fd,
165  *                                     void *context);
166  *
167  * DESCRIPTION
168  *
169  *    The task callback function.  This function will be called by the
170  *    scheduler when some event of the task is performed.  For example,
171  *    when data is available from the connection this will be called.
172  *
173  *    The `schedule' is the scheduler context, the `type' is the indicated
174  *    event, the `fd' is the file descriptor of the task and the `context'
175  *    is a caller specified context. If multiple events occurred this
176  *    callback is called separately for all events.  The `app_context'
177  *    is application specific context that was given as argument to the
178  *    silc_schedule_init function.  If the task is timeout task then `fd'
179  *    is zero (0).
180  *
181  *    To specify task callback function in the application using the
182  *    SILC_TASK_CALLBACK macro is recommended.
183  *
184  ***/
185 typedef void (*SilcTaskCallback)(SilcSchedule schedule, void *app_context,
186                                  SilcTaskEvent type, SilcUInt32 fd,
187                                  void *context);
188
189 /* Macros */
190
191 /****d* silcutil/SilcScheduleAPI/SILC_ALL_TASKS
192  *
193  * NAME
194  *
195  *    #define SILC_ALL_TASKS ...
196  *
197  * DESCRIPTION
198  *
199  *    Marks for all tasks in the scheduler. This can be passed to
200  *    silc_schedule_task_del function to delete all tasks at once.
201  *
202  * SOURCE
203  */
204 #define SILC_ALL_TASKS ((SilcTask)1)
205 /***/
206
207 /****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
208  *
209  * NAME
210  *
211  *    #define SILC_TASK_CALLBACK ...
212  *
213  * DESCRIPTION
214  *
215  *    Generic macro to define task callback functions. This defines a
216  *    static function with name `func' as a task callback function.
217  *
218  * SOURCE
219  */
220 #define SILC_TASK_CALLBACK(func)                                        \
221 void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type, \
222           SilcUInt32 fd, void *context)
223 /***/
224
225 /* Prototypes */
226
227 /****f* silcutil/SilcScheduleAPI/silc_schedule_init
228  *
229  * SYNOPSIS
230  *
231  *    SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
232  *
233  * DESCRIPTION
234  *
235  *    Initializes the scheduler. This returns the scheduler context that
236  *    is given as argument usually to all silc_schedule_* functions.
237  *    The `app_context' is application specific context that is delivered
238  *    to all task callbacks. The caller must free that context.  The
239  *    'app_context' can be for example the application itself.
240  *
241  *    The `max_tasks' is the maximum number of SILC_TASK_FD tasks in the
242  *    scheduler.  Set value to 0 to use default.  Operating system will
243  *    enforce the final limit.  On some operating systems the limit can
244  *    be significantly increased when this function is called in priviliged
245  *    mode (as super user).
246  *
247  ***/
248 SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
249
250 /****f* silcutil/SilcScheduleAPI/silc_schedule_uninit
251  *
252  * SYNOPSIS
253  *
254  *    SilcBool silc_schedule_uninit(SilcSchedule schedule);
255  *
256  * DESCRIPTION
257  *
258  *    Uninitializes the scheduler. This is called when the program is ready
259  *    to end. This removes all tasks from the scheduler. Returns FALSE if the
260  *    scheduler could not be uninitialized. This happens when the scheduler
261  *    is still valid and silc_schedule_stop has not been called.
262  *
263  ***/
264 SilcBool silc_schedule_uninit(SilcSchedule schedule);
265
266 /****f* silcutil/SilcScheduleAPI/silc_schedule_stop
267  *
268  * SYNOPSIS
269  *
270  *    void silc_schedule_stop(SilcSchedule schedule);
271  *
272  * DESCRIPTION
273  *
274  *    Stops the scheduler even if it is not supposed to be stopped yet.
275  *    After calling this, one must call silc_schedule_uninit (after the
276  *    silc_schedule has returned).  After this is called it is guaranteed
277  *    that next time the scheduler enters the main loop it will be stopped.
278  *    However, untill it enters the main loop it will not detect that
279  *    it is stopped for example if this is called from another thread.
280  *
281  ***/
282 void silc_schedule_stop(SilcSchedule schedule);
283
284 /****f* silcutil/SilcScheduleAPI/silc_schedule
285  *
286  * SYNOPSIS
287  *
288  *    void silc_schedule(SilcSchedule schedule);
289  *
290  * DESCRIPTION
291  *
292  *    The SILC scheduler. The program will run inside this function.
293  *    When this returns the program is to be ended. Before this function can
294  *    be called, one must call silc_schedule_init function.
295  *
296  ***/
297 void silc_schedule(SilcSchedule schedule);
298
299 /****f* silcutil/SilcScheduleAPI/silc_schedule_one
300  *
301  * SYNOPSIS
302  *
303  *    SilcBool silc_schedule_one(SilcSchedule schedule, int block);
304  *
305  * DESCRIPTION
306  *
307  *    Same as the silc_schedule but runs the scheduler only one round
308  *    and then returns.  This function is handy when the SILC scheduler
309  *    is used inside some other external scheduler, for example.  If
310  *    the `timeout_usecs' is non-negative a timeout will be added to the
311  *    scheduler.  The function will not return in this timeout unless
312  *    some other event occurs.
313  *
314  ***/
315 SilcBool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
316
317 /****f* silcutil/SilcScheduleAPI/silc_schedule_wakeup
318  *
319  * SYNOPSIS
320  *
321  *    void silc_schedule_wakeup(SilcSchedule schedule);
322  *
323  * DESCRIPTION
324  *
325  *    Wakes up the scheduler. This is used only in multi-threaded
326  *    environments where threads may add new tasks or remove old tasks
327  *    from the scheduler. This is called to wake up the scheduler in the
328  *    main thread so that it detects the changes in the scheduler.
329  *    If threads support is not compiled in this function has no effect.
330  *    Implementation of this function may be platform specific.
331  *
332  ***/
333 void silc_schedule_wakeup(SilcSchedule schedule);
334
335 /****f* silcutil/SilcScheduleAPI/silc_schedule_get_context
336  *
337  * SYNOPSIS
338  *
339  *    void *silc_schedule_get_context(SilcSchedule schedule);
340  *
341  * DESCRIPTION
342  *
343  *    Returns the application specific context that was saved into the
344  *    scheduler in silc_schedule_init function.  The context is also
345  *    returned to application in task callback functions, but this function
346  *    may be used to get it as well if needed.
347  *
348  ***/
349 void *silc_schedule_get_context(SilcSchedule schedule);
350
351 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add_fd
352  *
353  * SYNOPSIS
354  *
355  *    SilcTask
356  *    silc_schedule_task_add_fd(SilcSchedule schedule, SilcUInt32 fd,
357  *                              SilcTaskCallback callback, void *context);
358  *
359  * DESCRIPTION
360  *
361  *    Add file descriptor task to scheduler.  The `fd' may be either real
362  *    file descriptor, socket or on some platforms an opaque file descriptor
363  *    handle.  To receive events for the file descriptor set the correct
364  *    request events with silc_schedule_set_listen_fd function.
365  *
366  ***/
367 #define silc_schedule_task_add_fd(schedule, fd, callback, context)      \
368   silc_schedule_task_add(schedule, fd, callback, context, 0, 0, SILC_TASK_FD)
369
370 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add_timeout
371  *
372  * SYNOPSIS
373  *
374  *    SilcTask
375  *    silc_schedule_task_add_timeout(SilcSchedule schedule,
376  *                                   SilcTaskCallback callback, void *context,
377  *                                   long seconds, long useconds);
378  *
379  * DESCRIPTION
380  *
381  *    Add timeout task to scheduler.  The `callback' will be called once
382  *    the specified timeout has elapsed.  The task will be removed from the
383  *    scheduler automatically once the task expires.  The event returned
384  *    to the `callback' is SILC_TASK_EXPIRE.
385  *
386  ***/
387 #define silc_schedule_task_add_timeout(schedule, callback, context, s, u) \
388   silc_schedule_task_add(schedule, 0, callback, context, s, u,            \
389                          SILC_TASK_TIMEOUT)
390
391 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add_signal
392  *
393  * SYNOPSIS
394  *
395  *    SilcTask
396  *    silc_schedule_task_add_signal(SilcSchedule schedule, int signal,
397  *                                  SilcTaskCallback callback, void *context);
398  *
399  * DESCRIPTION
400  *
401  *    Add platform specific process signal handler to scheduler.  On Unix
402  *    systems the `signal' is one of the signal specified in signal(7).  On
403  *    other platforms this function may not be available at all, and has no
404  *    effect when called.  The event delivered to the `callback' is
405  *    SILC_TASK_INTERRUPT.
406  *
407  * NOTES
408  *
409  *    One signal may be registered only one callback.  Adding second callback
410  *    for signal that already has one will fail.
411  *
412  *    This function always returns NULL.  To remove signal from scheduler by
413  *    the signal call silc_schedule_task_del_by_fd.
414  *
415  ***/
416 #define silc_schedule_task_add_signal(schedule, signal, callback, context) \
417   silc_schedule_task_add(schedule, signal, callback, context, 0, 0,     \
418                          SILC_TASK_SIGNAL)
419
420 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del
421  *
422  * SYNOPSIS
423  *
424  *    void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
425  *
426  * DESCRIPTION
427  *
428  *    Deletes the `task' from the scheduler indicated by the `schedule'.
429  *    After deleting the task it is guaranteed that the task callback
430  *    will not be called. If the `task' is SILC_ALL_TASKS then all
431  *    tasks is removed from the scheduler.
432  *
433  *    It is safe to call this function in any place. Tasks may be removed
434  *    in task callbacks (including in the task's own task callback) and
435  *    in multi-threaded environment in other threads as well.
436  *
437  ***/
438 void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
439
440 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_fd
441  *
442  * SYNOPSIS
443  *
444  *    void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd);
445  *
446  * DESCRIPTION
447  *
448  *    Deletes a task from the scheduler by the specified `fd'.
449  *
450  *    It is safe to call this function in any place. Tasks may be removed
451  *    in task callbacks (including in the task's own task callback) and
452  *    in multi-threaded environment in other threads as well.
453  *
454  ***/
455 void silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd);
456
457 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_callback
458  *
459  * SYNOPSIS
460  *
461  *    void silc_schedule_task_del_by_callback(SilcSchedule schedule,
462  *                                            SilcTaskCallback callback);
463  *
464  * DESCRIPTION
465  *
466  *    Deletes a task from the scheduler by the specified `callback' task
467  *    callback function.
468  *
469  *    It is safe to call this function in any place. Tasks may be removed
470  *    in task callbacks (including in the task's own task callback) and
471  *    in multi-threaded environment in other threads as well.
472  *
473  ***/
474 void silc_schedule_task_del_by_callback(SilcSchedule schedule,
475                                         SilcTaskCallback callback);
476
477 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_context
478  *
479  * SYNOPSIS
480  *
481  *    void silc_schedule_task_del_by_context(SilcSchedule schedule,
482  *                                           void *context);
483  *
484  * DESCRIPTION
485  *
486  *    Deletes a task from the scheduler by the specified `context'.
487  *
488  *    It is safe to call this function in any place. Tasks may be removed
489  *    in task callbacks (including in the task's own task callback) and
490  *    in multi-threaded environment in other threads as well.
491  *
492  ***/
493 void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
494
495 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_all
496  *
497  * SYNOPSIS
498  *
499  *    void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
500  *                                       SilcTaskCallback callback,
501  *                                       void *context);
502  *
503  * DESCRIPTION
504  *
505  *    Deletes a task from the scheduler by the specified `fd', `callback'
506  *    and `context'.
507  *
508  *    It is safe to call this function in any place. Tasks may be removed
509  *    in task callbacks (including in the task's own task callback) and
510  *    in multi-threaded environment in other threads as well.
511  *
512  ***/
513 void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
514                                    SilcTaskCallback callback, void *context);
515
516 /****f* silcutil/SilcScheduleAPI/silc_schedule_set_listen_fd
517  *
518  * SYNOPSIS
519  *
520  *    void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
521  *                                     SilcTaskEvent mask,
522  *                                     SilcBool send_events);
523  *
524  * DESCRIPTION
525  *
526  *    Sets a file descriptor `fd' to be listened by the scheduler for
527  *    `mask' events.  To tell scheduler not to listen anymore for this
528  *    file descriptor call the silc_schedule_unset_listen_fd function.
529  *    When new task is created with silc_schedule_task_add the event
530  *    for the task's fd is initially set to SILC_TASK_READ. If you need
531  *    to control the task's fd's events you must call this function
532  *    whenever you need to change the events. This can be called multiple
533  *    times to change the events.
534  *
535  *    If the `send_events' is TRUE then this function sends the events
536  *    in `mask' to the application.  If FALSE then they are sent only
537  *    after the event occurs in reality.  In normal cases the `send_events'
538  *    is set to FALSE.
539  *
540  ***/
541 void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
542                                  SilcTaskEvent mask, SilcBool send_events);
543
544 /****f* silcutil/SilcScheduleAPI/silc_schedule_unset_listen_fd
545  *
546  * SYNOPSIS
547  *
548  *    void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd);
549  *
550  * DESCRIPTION
551  *
552  *    Tells the scheduler not to listen anymore for the specified
553  *    file descriptor `fd'. No events will be detected for the `fd'
554  *    after calling this function.
555  *
556  ***/
557 void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd);
558
559 #include "silcschedule_i.h"
560
561 #endif