updates.
[silc.git] / lib / silcutil / silctask.h
1 /*
2
3   silctask.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1998 - 2001 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20
21 #ifndef SILCTASK_H
22 #define SILCTASK_H
23
24 typedef struct SilcTaskQueueStruct *SilcTaskQueue;
25 typedef struct SilcTaskStruct *SilcTask;
26 typedef void (*SilcTaskCallback)(void *, int, void *, int);
27
28 #include "silcschedule.h"
29
30 /* 
31    SILC Task object. 
32
33    int fd
34
35        File descriptor. This usually is a network socket but can be
36        any file descriptor. On generic tasks, that applies to all file
37        descriptors, this is set to -1.
38
39    struct timeval timeout
40   
41        The timeout when this task is supposed to be run. This is defined
42        only if the task is a timeout task.
43
44    void *context;
45
46        Context structure passed to callback function as argument.
47
48    SilcTaskCallback callback
49
50        The callback function Silc scheduler calls when this task is scheduled
51        to be run. First argument is the task queue this task belongs to. This
52        is a void pointer and the task queue has to casted out of it. Second
53        argument is the type of the event just occured inside the scheduler 
54        (SILC_TASK_READ or SILC_TASK_WRITE). Third argument is the context 
55        structure of the task. Last argument is the file descriptor of the
56        task.
57
58    bool valid
59
60        Marks for validity of the task. Task that is not valid scheduler 
61        will skip. This is boolean value.
62
63    int priority
64
65        Priority of the task. This field is used internally only and it
66        should not be touched otherwise.
67
68    int iomask
69
70        I/O mask which tells to the scheduler for what kind of I/O this 
71        task is ready. If the task is ready for both reading and writing
72        SILC_TASK_READ and SILC_TASK_WRITE are masked into this variable.
73        Masking is done by OR'ing (1 << SILC_TASK_*) values. One can check
74        the mask by AND'ing (1L << SILC_TASK_*) against the mask. At the
75        registering of a new task this mask is set to SILC_TASK_READ by
76        default. If a task doesn't perform reading this value must be
77        reset to SILC_TASK_WRITE. If it performs both reading and writing
78        SILC_TASK_WRITE must be added to the mask. A task must always be 
79        ready for at least for one I/O type.
80
81    struct SilcTaskStruct *next
82    struct SilcTaskStruct *prev
83
84        Next and previous task. If the task is first in the list, prev is
85        set to the last task in the list. If the task is last in the list, 
86        next is set to the first task in the list (forms a circular list).
87
88 */
89
90 struct SilcTaskStruct {
91   int fd;
92   struct timeval timeout;
93   void *context;
94   SilcTaskCallback callback;
95   bool valid;
96   int priority;
97   int iomask;
98
99   struct SilcTaskStruct *next;
100   struct SilcTaskStruct *prev;
101 };
102
103 /* 
104    SILC Task types.
105
106    SILC has three types of tasks, non-timeout tasks (tasks that perform
107    over file descriptors), timeout tasks and generic tasks (tasks that apply
108    to every file descriptor). This type is sent as argument for the 
109    task registering function.
110
111 */
112 typedef enum {
113   SILC_TASK_FD,
114   SILC_TASK_TIMEOUT,
115   SILC_TASK_GENERIC,
116 } SilcTaskType;
117
118 /* 
119    SILC Task priorities.
120
121    Following description of the priorities uses timeout tasks as example
122    how the priority behaves. However, non-timeout tasks behaves same as
123    timeout tasks with following priorities.
124
125    SILC_TASK_PRI_LOW
126
127        Lowest priority. The task is scheduled to run after its timeout
128        has expired only and only when every other task with higher priority 
129        has already been run. For non-timeout tasks this priority behaves
130        same way. Life is not fair for tasks with this priority.
131
132    SILC_TASK_PRI_NORMAL
133
134        Normal priority that is used mostly in Silc. This is priority that
135        should always be used unless you specificly need some other priority.
136        The scheduler will run this task as soon as its timeout has expired.
137        For non-timeout tasks this priority behaves same way. Tasks are run 
138        in FIFO (First-In-First-Out) order.
139
140 */
141 typedef enum {
142   SILC_TASK_PRI_LOW,
143   SILC_TASK_PRI_NORMAL,
144 } SilcTaskPriority;
145
146 /* 
147    SILC Task Queue object. 
148    
149    Usually there are three task queues in SILC. Tasks with timeouts
150    has their own queue, tasks without timeout has one as well and generic
151    tasks has their own also. Scheduler has timeout queue hooks and 
152    non-timeout queue hooks in the scheduler and it does not check for 
153    timeouts in non-timeout hooks and vice versa, respectively. Ie. Register 
154    timeout queues to their own SilcTaskQueue pointer and non-timeout queues 
155    to their own pointer. 
156
157    Generic tasks, mentioned earlier, has their own task queue. These tasks 
158    are non-timeout tasks and they apply to all file descriptors, except to 
159    those that have explicitly registered a non-timeout task. These tasks
160    are there to make it simpler and faster to execute common code that
161    applies to all connections. These are, for example, receiving packets
162    from network and sending packets to network. It doesn't make much sense
163    to register a task that receives a packet from network to every connection
164    when you can have one task that applies to all connections. This is what
165    generic tasks are for. Generic tasks are not bound to any specific file
166    descriptor, however, the correct file descriptor must be passed as
167    argument to task registering function.
168
169    Short description of the field following:
170
171    SilcSchedule schedule
172
173        A back pointer to the scheduler.
174
175    SilcTask task
176
177        Pointer to the tasks in the queue.
178
179    int valid
180
181        Marks for validity of the queue. If the task queue is not valid 
182        scheduler will skip it. This is boolean value.
183
184    struct timeval timeout
185
186        Timeout when earliest some tasks in this queue should expire. The
187        value of this timeout is updated automatically by schedule. This 
188        is used only and only if this queue is a timeout queue. For normal
189        task queue this is not defined. This is meant only for internal
190        use and it should be considered to be read-only field.
191
192 */
193
194 struct SilcTaskQueueStruct {
195   SilcSchedule schedule;
196   SilcTask task;
197   int valid;
198   struct timeval timeout;
199 };
200
201 /* Marks for all tasks in a task queue. This can be passed to 
202    unregister_task function to cancel all tasks at once. */
203 #define SILC_ALL_TASKS ((SilcTask)1)
204
205 /* Marks for all task queues. This can be passed to 
206    silc_task_queue_unregister function to cancel all task queues at once. */
207 #define SILC_ALL_TASK_QUEUES ((SilcTaskQueue)1)
208
209 /* Silc Task event types. One of these are passed to the task callback
210    function from the schedule. These values are also masked into a task
211    so that scheduler knows for what kind of I/O it needs to perform
212    for that task. */
213 #define SILC_TASK_READ 0
214 #define SILC_TASK_WRITE 1
215
216 /* Macros */
217
218 /* These can be used instead of calling directly the registering function. 
219    XXX: These are not used currently, maybe they should be :) */
220 #define SILC_REGISTER_FD_TASK(queue, fd, cb, ctx, pri) \
221   (silc_task_register((queue), (fd), (cb), (ctx), 0, 0, \
222                       SILC_TASK_FD, (pri)))
223 #define SILC_REGISTER_TIMEOUT_TASK(queue, fd, cb, ctx, sec, usec, pri) \
224   (silc_task_register((queue), (fd), (cb), (ctx), (sec), (usec), \
225                       SILC_TASK_TIMEOUT, (pri)))
226 #define SILC_REGISTER_GENERIC_TASK(queue, fd, cb, ctx, pri) \
227   (silc_task_register((queue), (fd), (cb), (ctx), 0, 0, \
228                       SILC_TASK_GENERIC, (pri)))
229
230 /* Generic macro to define task callback functions. This defines a function
231    with name 'func' as a task callback function. */
232 #define SILC_TASK_CALLBACK(func) \
233 static void func(void *qptr, int type, void *context, int fd)
234 #define SILC_TASK_CALLBACK_GLOBAL(func) \
235 void func(void *qptr, int type, void *context, int fd)
236
237 /* Prototypes */
238 void silc_task_queue_alloc(SilcSchedule schedule, SilcTaskQueue *new, 
239                            bool valid);
240 void silc_task_queue_free(SilcTaskQueue queue);
241 SilcTask silc_task_add(SilcTaskQueue queue, SilcTask new, 
242                        SilcTaskPriority priority);
243 SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask new,
244                                SilcTaskPriority priority);
245 SilcTask silc_task_register(SilcTaskQueue queue, int fd, 
246                             SilcTaskCallback cb, void *context, 
247                             long seconds, long useconds, 
248                             SilcTaskType type, 
249                             SilcTaskPriority priority);
250 int silc_task_remove(SilcTaskQueue queue, SilcTask task);
251 void silc_task_unregister(SilcTaskQueue queue, SilcTask task);
252 void silc_task_unregister_by_fd(SilcTaskQueue queue, int fd);
253 void silc_task_unregister_by_callback(SilcTaskQueue queue, 
254                                       SilcTaskCallback callback);
255 void silc_task_unregister_by_context(SilcTaskQueue queue, void *context);
256 void silc_task_set_iotype(SilcTask task, int type);
257 void silc_task_reset_iotype(SilcTask task, int type);
258 int silc_task_timeout_compare(struct timeval *smaller, 
259                               struct timeval *bigger);
260
261 #endif