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