updates.
[crypto.git] / lib / silcutil / silcschedule.h
1 /****h* silcutil/silcschedule.h
2  *
3  * NAME
4  *
5  * silcschedule.h
6  *
7  * COPYRIGHT
8  *
9  * Author: Pekka Riikonen <priikone@silcnet.org>
10  *
11  * Copyright (C) 1998 - 2001 Pekka Riikonen
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  # DESCRIPTION
24  *
25  * The SILC Scheduler is the heart of any application. The scheduler provides
26  * the application's main loop that can handle incoming data, outgoing data,
27  * timeouts and dispatch different kind of tasks.
28  *
29  * The SILC Scheduler supports file descriptor based tasks, timeout tasks
30  * and generic tasks. File descriptor tasks are tasks that perform some 
31  * operation over the specified file descriptor. These include network 
32  * connections, for example. The timeout tasks are timeouts that are executed
33  * after the specified timeout has elapsed. The generic tasks are tasks that
34  * apply to all registered file descriptors thus providing one task that
35  * applies to many independent connections.
36  *
37  * The SILC Scheduler is designed to be the sole main loop of the application
38  * so that the application does not need any other main loop.  However,
39  * SILC Scheduler does support running the scheduler only once, so that the
40  * scheduler does not block, and thus providing a possiblity that some
41  * external main loop is run over the SILC Scheduler. However, these 
42  * applications are considered to be special cases.
43  *
44  * Typical application first initializes the scheduler and then registers
45  * the very first tasks to the scheduler and then run the scheduler.  After
46  * the scheduler's run function returns the application is considered to be 
47  * ended.
48  *
49  * On WIN32 systems the SILC Scheduler is also designed to work as the main
50  * loop of the GUI application. It can handle all Windows messages and
51  * it dispatches them from the scheduler and thus makes it possible to
52  * create GUI applications. The scheduler can also handle all kinds of
53  * WIN32 handles, this includes sockets created by the SILC Net API routines,
54  * WSAEVENT handle objects and arbitrary 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,
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_TIMEOUT is set always only
157  *    by the scheduler when timeout for timeout task occurs.
158  *
159  * SOURCE
160  */
161 typedef enum {
162   SILC_TASK_READ      = 0x0001,          /* Reading */
163   SILC_TASK_WRITE     = 0x0002,          /* Writing */
164   SILC_TASK_EXPIRE    = 0x0004,          /* Timeout */
165 } SilcTaskEvent;
166 /***/
167
168 /****d* silcutil/SilcScheduleAPI/SilcTaskPriority
169  *
170  * NAME
171  * 
172  *    typedef enum { ... } SilcTaskPriority
173  *
174  * DESCRIPTION
175  *
176  *    Task priorities. Tasks may be registered with different priorities.
177  *    This type defines the different task priorities. The priorities
178  *    behaves same for all type of tasks, fd tasks, timeout tasks and
179  *    generic tasks.
180  *
181  * SOURCE
182  */
183 typedef enum {
184   /* Lowest priority. The task is scheduled to run after its timeout
185      has expired only and only when every other task with higher priority 
186      has already been run. For non-timeout tasks this priority behaves
187      same way. Life is not fair for tasks with this priority. */
188   SILC_TASK_PRI_LOW,
189
190   /* Normal priority that is used mostly in Silc. This is priority that
191      should always be used unless you specificly need some other priority.
192      The scheduler will run this task as soon as its timeout has expired.
193      For non-timeout tasks this priority behaves same way. Tasks are run 
194      in FIFO (First-In-First-Out) order. */
195   SILC_TASK_PRI_NORMAL,
196 } SilcTaskPriority;
197 /***/
198
199 /****f* silcutil/SilcScheduleAPI/silc_schedule_init
200  *
201  * SYNOPSIS
202  *
203  *    typedef void (*SilcTaskCallback)(SilcSchedule schedule, 
204  *                                     SilcTaskEvent type, uint32 fd, 
205  *                                     void *context);
206  *
207  * DESCRIPTION
208  *
209  *    The task callback function.  This function will be called by the
210  *    scheduler when some event of the task is performed.  For example,
211  *    when data is available from the connection this will be called.
212  *
213  *    The `schedule' is the scheduler context, the `type' is the indicated
214  *    event, the `fd' is the file descriptor of the task and the `context'
215  *    is a caller specified context. If multiple events occurred this
216  *    call is called separately for all events.
217  *
218  *    To specify task callback function in the application using the
219  *    SILC_TASK_CALLBACK and SILC_TASK_CALLBACK_GLOBAL macros is
220  *    recommended.
221  *
222  ***/
223 typedef void (*SilcTaskCallback)(SilcSchedule schedule, SilcTaskEvent type,
224                                  uint32 fd, void *context);
225
226 /* Macros */
227
228 /****d* silcutil/SilcScheduleAPI/SILC_ALL_TASKS
229  *
230  * NAME
231  * 
232  *    #define SILC_ALL_TASKS ...
233  *
234  * DESCRIPTION
235  *
236  *    Marks for all tasks in the scheduler. This can be passed to 
237  *    silc_schedule_task_del function to delete all tasks at once.
238  *
239  * SOURCE
240  */
241 #define SILC_ALL_TASKS ((SilcTask)1)
242 /***/
243
244 /****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
245  *
246  * NAME
247  * 
248  *    #define SILC_TASK_CALLBACK ...
249  *
250  * DESCRIPTION
251  *
252  *    Generic macro to define task callback functions. This defines a
253  *    static function with name `func' as a task callback function.
254  *
255  * SOURCE
256  */
257 #define SILC_TASK_CALLBACK(func)                                \
258 static void func(SilcSchedule schedule, SilcTaskEvent type,     \
259                  uint32 fd, void *context)
260 /***/
261
262 /****d* silcutil/SilcScheduleAPI/SILC_TASK_CALLBACK
263  *
264  * NAME
265  * 
266  *    #define SILC_TASK_CALLBACK_GLOBAL ...
267  *
268  * DESCRIPTION
269  *
270  *    Generic macro to define task callback functions. This defines a
271  *    function with name `func' as a task callback function.  This
272  *    differs from SILC_TASK_CALLBACK in that the defined function is
273  *    not static function.
274  *
275  * SOURCE
276  */
277 #define SILC_TASK_CALLBACK_GLOBAL(func)                 \
278 void func(SilcSchedule schedule, SilcTaskEvent type,    \
279           uint32 fd, void *context)
280 /***/
281
282 /* Prototypes */
283
284 /****f* silcutil/SilcScheduleAPI/silc_schedule_init
285  *
286  * SYNOPSIS
287  *
288  *    SilcSchedule silc_schedule_init(int max_tasks);
289  *
290  * DESCRIPTION
291  *
292  *    Initializes the scheduler. This returns the scheduler context that
293  *    is given as arugment usually to all silc_schedule_* functions.
294  *    The `max_tasks' indicates the number of maximum tasks that the
295  *    scheduler can handle.
296  *
297  ***/
298 SilcSchedule silc_schedule_init(int max_tasks);
299
300 /****f* silcutil/SilcScheduleAPI/silc_schedule_uninit
301  *
302  * SYNOPSIS
303  *
304  *    bool silc_schedule_uninit(SilcSchedule schedule);
305  *
306  * DESCRIPTION
307  *
308  *    Uninitializes the schedule. This is called when the program is ready
309  *    to end. This removes all tasks from the scheduler. Returns FALSE if the
310  *    scheduler could not be uninitialized. This happens when the scheduler
311  *    is still valid and silc_schedule_stop has not been called.
312  *
313  ***/
314 bool silc_schedule_uninit(SilcSchedule schedule);
315
316 /****f* silcutil/SilcScheduleAPI/silc_schedule_stop
317  *
318  * SYNOPSIS
319  *
320  *    void silc_schedule_stop(SilcSchedule schedule);
321  *
322  * DESCRIPTION
323  *
324  *    Stops the scheduler even if it is not supposed to be stopped yet. 
325  *    After calling this, one must call silc_schedule_uninit (after the 
326  *    silc_schedule has returned).
327  *
328  ***/
329 void silc_schedule_stop(SilcSchedule schedule);
330
331 /****f* silcutil/SilcScheduleAPI/silc_schedule
332  *
333  * SYNOPSIS
334  *
335  *    void silc_schedule(SilcSchedule schedule);
336  *
337  * DESCRIPTION
338  *
339  *    The SILC scheduler. This is actually the main routine in SILC programs.
340  *    When this returns the program is to be ended. Before this function can
341  *    be called, one must call silc_schedule_init function.
342  *
343  ***/
344 void silc_schedule(SilcSchedule schedule);
345
346 /****f* silcutil/SilcScheduleAPI/silc_schedule
347  *
348  * SYNOPSIS
349  *
350  *    bool silc_schedule_one(SilcSchedule schedule, int block);
351  *
352  * DESCRIPTION
353  *
354  *    Same as the silc_schedule but runs the scheduler only one round
355  *    and then returns.  This function is handy when the SILC scheduler
356  *    is used inside some other external scheduler, for example.  If
357  *    the `timeout_usecs' is non-negative a timeout will be added to the
358  *    scheduler.  The function will not return in this timeout unless
359  *    some other event occurs.
360  *
361  ***/
362 bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs);
363
364 /****f* silcutil/SilcScheduleAPI/silc_schedule_wakeup
365  *
366  * SYNOPSIS
367  *
368  *    void silc_schedule_wakeup(SilcSchedule schedule);
369  *
370  * DESCRIPTION
371  *
372  *    Wakes up the scheduler. This is used only in multi-threaded
373  *    environments where threads may add new tasks or remove old tasks
374  *    from the scheduler. This is called to wake up the scheduler in the
375  *    main thread so that it detects the changes in the scheduler.
376  *    If threads support is not compiled in this function has no effect.
377  *    Implementation of this function may be platform specific.
378  *
379  ***/
380 void silc_schedule_wakeup(SilcSchedule schedule);
381
382 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add
383  *
384  * SYNOPSIS
385  *
386  *    SilcTask silc_schedule_task_add(SilcSchedule schedule, uint32 fd,
387  *                                    SilcTaskCallback callback, 
388  *                                    void *context, 
389  *                                    long seconds, long useconds, 
390  *                                    SilcTaskType type, 
391  *                                    SilcTaskPriority priority);
392  *
393  * DESCRIPTION
394  *
395  *    Registers a new task to the scheduler. This same function is used
396  *    to register all types of tasks. The `type' argument tells what type
397  *    of the task is. Note that when registering non-timeout tasks one
398  *    should also pass 0 as timeout, as the timeout will be ignored anyway. 
399  *    Also, note, that one cannot register timeout task with 0 timeout.
400  *    There cannot be zero timeouts, passing zero means no timeout is used
401  *    for the task and SILC_TASK_FD_TASK is used as default task type in
402  *    this case.
403  *
404  *    The `schedule' is the scheduler context. The `fd' is the file
405  *    descriptor of the task. On WIN32 systems the `fd' is not actual
406  *    file descriptor but some WIN32 event handle. On WIN32 system the `fd'
407  *    may be a socket created by the SILC Net API routines, WSAEVENT object
408  *    created by Winsock2 network routines or arbitrary WIN32 HANDLE object.
409  *    On Unix systems the `fd' is always the real file descriptor.
410  *
411  *    The `callback' is the task callback that will be called when some
412  *    event occurs for this task. The `context' is sent as argument to
413  *    the task `callback' function. For timeout tasks the callback is
414  *    called after the specified timeout has elapsed.
415  *
416  *    If the `type' is SILC_TASK_TIMEOUT then `seconds' and `useconds'
417  *    may be non-zero.  Otherwise they should be zero. The `priority'
418  *    indicates the priority of the task.
419  *
420  *    It is always safe to call this function in any place. New tasks
421  *    may be added also in task callbacks, and in multi-threaded environment
422  *    in other threads as well.
423  *   
424  ***/
425 SilcTask silc_schedule_task_add(SilcSchedule schedule, uint32 fd,
426                                 SilcTaskCallback callback, void *context, 
427                                 long seconds, long useconds, 
428                                 SilcTaskType type, 
429                                 SilcTaskPriority priority);
430
431 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del
432  *
433  * SYNOPSIS
434  *
435  *    void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
436  *
437  * DESCRIPTION
438  *
439  *    Deletes the `task' from the scheduler indicated by the `schedule'.
440  *    After deleting the task it is guaranteed that the task callback
441  *    will not be called. If the `task' is SILC_ALL_TASKS then all
442  *    tasks is removed from the scheduler.
443  *
444  *    It is safe to call this function in any place. Tasks may be removed
445  *    in task callbacks (including in the task's own task callback) and
446  *    in multi-threaded environment in other threads as well.
447  *
448  ***/
449 void silc_schedule_task_del(SilcSchedule schedule, SilcTask task);
450
451 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_fd
452  *
453  * SYNOPSIS
454  *
455  *    void silc_schedule_task_del_by_fd(SilcSchedule schedule, uint32 fd);
456  *
457  * DESCRIPTION
458  *
459  *    Deletes a task from the scheduler by the specified `fd'.
460  *
461  *    It is safe to call this function in any place. Tasks may be removed
462  *    in task callbacks (including in the task's own task callback) and
463  *    in multi-threaded environment in other threads as well.
464  *
465  ***/
466 void silc_schedule_task_del_by_fd(SilcSchedule schedule, uint32 fd);
467
468 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_callback
469  *
470  * SYNOPSIS
471  *
472  *    void silc_schedule_task_del_by_callback(SilcSchedule schedule,
473  *                                            SilcTaskCallback callback);
474  *
475  * DESCRIPTION
476  *
477  *    Deletes a task from the scheduler by the specified `callback' task
478  *    callback function.
479  *
480  *    It is safe to call this function in any place. Tasks may be removed
481  *    in task callbacks (including in the task's own task callback) and
482  *    in multi-threaded environment in other threads as well.
483  *
484  ***/
485 void silc_schedule_task_del_by_callback(SilcSchedule schedule,
486                                         SilcTaskCallback callback);
487
488 /****f* silcutil/SilcScheduleAPI/silc_schedule_task_del_by_context
489  *
490  * SYNOPSIS
491  *
492  *    void silc_schedule_task_del_by_context(SilcSchedule schedule, 
493  *                                           void *context);
494  *
495  * DESCRIPTION
496  *
497  *    Deletes a task from the scheduler by the specified `context'.
498  *
499  *    It is safe to call this function in any place. Tasks may be removed
500  *    in task callbacks (including in the task's own task callback) and
501  *    in multi-threaded environment in other threads as well.
502  *
503  ***/
504 void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context);
505
506 /****f* silcutil/SilcScheduleAPI/silc_schedule_set_listen_fd
507  *
508  * SYNOPSIS
509  *
510  *    void silc_schedule_set_listen_fd(SilcSchedule schedule, uint32 fd,
511  *                                     SilcTaskEvent mask);
512  *
513  * DESCRIPTION
514  *
515  *    Sets a file descriptor `fd' to be listened by the scheduler for
516  *    `mask' events.  To tell scheduler not to listen anymore for this
517  *    file descriptor call the silc_schedule_unset_listen_fd function.
518  *    When new task is created with silc_schedule_task_add the event
519  *    for the task's fd is initially set to SILC_TASK_READ. If you need
520  *    to control the task's fd's events you must call this function
521  *    whenever you need to change the events. This can be called multiple
522  *    times to change the events.
523  *
524  ***/
525 void silc_schedule_set_listen_fd(SilcSchedule schedule, uint32 fd,
526                                  SilcTaskEvent mask);
527
528 /****f* silcutil/SilcScheduleAPI/silc_schedule_unset_listen_fd
529  *
530  * SYNOPSIS
531  *
532  *    void silc_schedule_unset_listen_fd(SilcSchedule schedule, uint32 fd);
533  *
534  * DESCRIPTION
535  *
536  *    Tells the scheduler not to listen anymore for the specified
537  *    file descriptor `fd'. No events will be detected for the `fd'
538  *    after calling this function.
539  *
540  ***/
541 void silc_schedule_unset_listen_fd(SilcSchedule schedule, uint32 fd);
542
543 #endif