5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1998 - 2001 Pekka Riikonen
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.
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.
24 typedef struct SilcTaskQueueStruct *SilcTaskQueue;
25 typedef struct SilcTaskStruct *SilcTask;
26 typedef void (*SilcTaskCallback)(void *, int, void *, int);
28 #include "silcschedule.h"
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.
39 struct timeval timeout
41 The timeout when this task is supposed to be run. This is defined
42 only if the task is a timeout task.
46 Context structure passed to callback function as argument.
48 SilcTaskCallback callback
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
60 Marks for validity of the task. Task that is not valid scheduler
61 will skip. This is boolean value.
65 Priority of the task. This field is used internally only and it
66 should not be touched otherwise.
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.
81 struct SilcTaskStruct *next
82 struct SilcTaskStruct *prev
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).
90 struct SilcTaskStruct {
92 struct timeval timeout;
94 SilcTaskCallback callback;
99 struct SilcTaskStruct *next;
100 struct SilcTaskStruct *prev;
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.
119 SILC Task priorities.
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.
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.
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.
143 SILC_TASK_PRI_NORMAL,
147 SILC Task Queue object.
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.
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.
169 Short description of the field following:
171 SilcSchedule schedule
173 A back pointer to the scheduler.
177 Pointer to the tasks in the queue.
181 Marks for validity of the queue. If the task queue is not valid
182 scheduler will skip it. This is boolean value.
184 struct timeval timeout
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.
194 struct SilcTaskQueueStruct {
195 SilcSchedule schedule;
198 struct timeval timeout;
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)
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)
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
213 #define SILC_TASK_READ 0
214 #define SILC_TASK_WRITE 1
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)))
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)
238 void silc_task_queue_alloc(SilcSchedule schedule, SilcTaskQueue *new,
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,
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);