aa5830942db482c62363cb8d52e974cc68da9056
[oweals/gnunet.git] / gnunet_scheduler_lib.h
1 /*
2       This file is part of GNUnet
3       (C) 2009 Christian Grothoff (and other contributing authors)
4
5       GNUnet is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published
7       by the Free Software Foundation; either version 2, or (at your
8       option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       General Public License for more details.
14
15       You should have received a copy of the GNU General Public License
16       along with GNUnet; see the file COPYING.  If not, write to the
17       Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18       Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file include/gnunet_scheduler_lib.h
23  * @brief API to schedule computations using continuation passing style
24  * @author Christian Grothoff
25  */
26
27 #ifndef GNUNET_SCHEDULER_LIB_H
28 #define GNUNET_SCHEDULER_LIB_H
29
30 #ifdef __cplusplus
31 extern "C"
32 {
33 #if 0                           /* keep Emacsens' auto-indent happy */
34 }
35 #endif
36 #endif
37
38 #include "gnunet_time_lib.h"
39
40
41 /**
42  * Opaque handle for the scheduling service.
43  */
44 struct GNUNET_SCHEDULER_Handle;
45
46
47 /**
48  * Opaque reference to a task.
49  */
50 typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier;
51
52
53 /**
54  * Constant used to indicate that the scheduled
55  * task has no others as prerequisites.
56  */
57 #define GNUNET_SCHEDULER_NO_PREREQUISITE_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0)
58
59 /**
60  * Reasons why the schedule may have triggered
61  * the task now.
62  */
63 enum GNUNET_SCHEDULER_Reason
64 {
65   /**
66    * This is the very first task run during startup.
67    */
68   GNUNET_SCHEDULER_REASON_STARTUP = 0,
69
70   /**
71    * We are shutting down and are running all shutdown-related tasks
72    * (regardless of timeout, etc.).
73    */
74   GNUNET_SCHEDULER_REASON_SHUTDOWN = 1,
75
76   /**
77    * The specified timeout has expired.
78    * (also set if the delay given was 0).
79    */
80   GNUNET_SCHEDULER_REASON_TIMEOUT = 2,
81
82   /**
83    * The reading socket is ready.
84    */
85   GNUNET_SCHEDULER_REASON_READ_READY = 4,
86
87   /**
88    * The writing socket is ready.
89    */
90   GNUNET_SCHEDULER_REASON_WRITE_READY = 8,
91
92   /**
93    * The prerequisite task is done.
94    */
95   GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16
96 };
97
98
99 /**
100  * Valid task priorities.  Use these, do not
101  * pass random integers!
102  */
103 enum GNUNET_SCHEDULER_Priority
104 {
105   /**
106    * Run with the same priority as the current job.
107    */
108   GNUNET_SCHEDULER_PRIORITY_KEEP = 0,
109
110   /**
111    * Run when otherwise idle.
112    */
113   GNUNET_SCHEDULER_PRIORITY_IDLE = 1,
114
115   /**
116    * Run as background job (higher than idle,
117    * lower than default).
118    */
119   GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2,
120
121   /**
122    * Run with the default priority (normal
123    * P2P operations).  Higher than BACKGROUND.
124    */
125   GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3,
126
127   /**
128    * Run with high priority (important requests).
129    * Higher than DEFAULT.
130    */
131   GNUNET_SCHEDULER_PRIORITY_HIGH = 4,
132
133   /**
134    * Run with priority for interactive tasks.
135    * Higher than "HIGH".
136    */
137   GNUNET_SCHEDULER_PRIORITY_UI = 5,
138
139   /**
140    * Run with priority for urgent tasks.  Use
141    * for things like aborts and shutdowns that
142    * need to preempt "UI"-level tasks.
143    * Higher than "UI".
144    */
145   GNUNET_SCHEDULER_PRIORITY_URGENT = 6,
146
147   /**
148    * Number of priorities (must be the last priority).
149    * This priority must not be used by clients.
150    */
151   GNUNET_SCHEDULER_PRIORITY_COUNT = 7
152 };
153
154
155 /**
156  * Context information passed to each scheduler task.
157  */
158 struct GNUNET_SCHEDULER_TaskContext
159 {
160
161   /**
162    * Scheduler running the task
163    */
164   struct GNUNET_SCHEDULER_Handle *sched;
165
166   /**
167    * Reason why the task is run now
168    */
169   enum GNUNET_SCHEDULER_Reason reason;
170
171   /**
172    * Set of file descriptors ready for reading;
173    * note that additional bits may be set
174    * that were not in the original request
175    */
176   const fd_set *read_ready;
177
178   /**
179    * Set of file descriptors ready for writing;
180    * note that additional bits may be set
181    * that were not in the original request.
182    */
183   const fd_set *write_ready;
184
185 };
186
187
188 /**
189  * Signature of the main function of a task.
190  *
191  * @param cls closure
192  * @param tc context information (why was this task triggered now)
193  */
194 typedef void (*GNUNET_SCHEDULER_Task) (void *cls,
195                                        const struct
196                                        GNUNET_SCHEDULER_TaskContext * tc);
197
198
199 /**
200  * Initialize and run scheduler.  This function will return when
201  * either a shutdown was initiated (via signal) and all tasks marked
202  * to "run_on_shutdown" have been completed or when all tasks in
203  * general have been completed.
204  *
205  * @param task task to run immediately
206  * @param cls closure of task
207  */
208 void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *cls);
209
210
211 /**
212  * Request the shutdown of a scheduler.  This function can be used to
213  * stop a scheduler, for example from within the signal
214  * handler for signals causing shutdowns.
215  */
216 void GNUNET_SCHEDULER_shutdown (struct GNUNET_SCHEDULER_Handle *sched);
217
218
219 /**
220  * Get information about the current load of this scheduler.  Use this
221  * function to determine if an elective task should be added or simply
222  * dropped (if the decision should be made based on the number of
223  * tasks ready to run).
224  *
225  * @param sched scheduler to query
226  * @param p priority-level to query, use KEEP to query the level
227  *          of the current task, use COUNT to get the sum over
228  *          all priority levels
229  * @return number of tasks pending right now
230  */
231 unsigned int GNUNET_SCHEDULER_get_load (struct GNUNET_SCHEDULER_Handle *sched,
232                                         enum GNUNET_SCHEDULER_Priority p);
233
234
235 /**
236  * Cancel the task with the specified identifier.
237  * The task must not yet have run.
238  *
239  * @param sched scheduler to use
240  * @param task id of the task to cancel
241  * @return the closure of the callback of the cancelled task
242  */
243 void *GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Handle *sched,
244                                GNUNET_SCHEDULER_TaskIdentifier task);
245
246
247 /**
248  * Continue the current execution with the given function.  This is
249  * similar to the other "add" functions except that there is no delay
250  * and the reason code can be specified.
251  *
252  * @param sched scheduler to use
253  * @param main main function of the task
254  * @param cls closure of task
255  * @param reason reason for task invocation
256  */
257 void
258 GNUNET_SCHEDULER_add_continuation (struct GNUNET_SCHEDULER_Handle *sched,
259                                    int run_on_shutdown,
260                                    GNUNET_SCHEDULER_Task main,
261                                    void *cls,
262                                    enum GNUNET_SCHEDULER_Reason reason);
263
264
265 /**
266  * Schedule a new task to be run after the specified
267  * prerequisite task has completed.
268  *
269  * @param sched scheduler to use
270  * @param run_on_shutdown run on shutdown?
271  * @param prio how important is this task?
272  * @param prerequisite_task run this task after the task with the given
273  *        task identifier completes (and any of our other
274  *        conditions, such as delay, read or write-readyness
275  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_PREREQUISITE_TASK to not have any dependency
276  *        on completion of other tasks.
277  * @param main main function of the task
278  * @param cls closure of task
279  * @return unique task identifier for the job
280  *         only valid until "main" is started!
281  */
282 GNUNET_SCHEDULER_TaskIdentifier
283 GNUNET_SCHEDULER_add_after (struct GNUNET_SCHEDULER_Handle *sched,
284                             int run_on_shutdown,
285                             enum GNUNET_SCHEDULER_Priority prio,
286                             GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
287                             GNUNET_SCHEDULER_Task main, void *cls);
288
289
290 /**
291  * Schedule a new task to be run with a specified delay.  The task
292  * will be scheduled for execution once the delay has expired and the
293  * prerequisite task has completed.
294  *
295  * @param sched scheduler to use
296  * @param run_on_shutdown run on shutdown? You can use this
297  *        argument to run a function only during shutdown
298  *        by setting delay to -1.  Set this
299  *        argument to GNUNET_NO to skip this task if
300  *        the user requested process termination.
301  * @param prio how important is this task?
302  * @param prerequisite_task run this task after the task with the given
303  *        task identifier completes (and any of our other
304  *        conditions, such as delay, read or write-readyness
305  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_PREREQUISITE_TASK to not have any dependency
306  *        on completion of other tasks.
307  * @param delay how long should we wait? Use  GNUNET_TIME_UNIT_FOREVER_REL for "forever"
308  * @param main main function of the task
309  * @param cls closure of task
310  * @return unique task identifier for the job
311  *         only valid until "main" is started!
312  */
313 GNUNET_SCHEDULER_TaskIdentifier
314 GNUNET_SCHEDULER_add_delayed (struct GNUNET_SCHEDULER_Handle *sched,
315                               int run_on_shutdown,
316                               enum GNUNET_SCHEDULER_Priority prio,
317                               GNUNET_SCHEDULER_TaskIdentifier
318                               prerequisite_task,
319                               struct GNUNET_TIME_Relative delay,
320                               GNUNET_SCHEDULER_Task main, void *cls);
321
322
323 /**
324  * Schedule a new task to be run with a specified delay or when the
325  * specified file descriptor is ready for reading.  The delay can be
326  * used as a timeout on the socket being ready.  The task will be
327  * scheduled for execution once either the delay has expired or the
328  * socket operation is ready.
329  *
330  * @param sched scheduler to use
331  * @param run_on_shutdown run on shutdown? Set this
332  *        argument to GNUNET_NO to skip this task if
333  *        the user requested process termination.
334  * @param prio how important is this task?
335  * @param prerequisite_task run this task after the task with the given
336  *        task identifier completes (and any of our other
337  *        conditions, such as delay, read or write-readyness
338  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_PREREQUISITE_TASK to not have any dependency
339  *        on completion of other tasks.
340  * @param delay how long should we wait? Use  GNUNET_TIME_UNIT_FOREVER_REL for "forever"
341  * @param rfd read file-descriptor
342  * @param main main function of the task
343  * @param cls closure of task
344  * @return unique task identifier for the job
345  *         only valid until "main" is started!
346  */
347 GNUNET_SCHEDULER_TaskIdentifier
348 GNUNET_SCHEDULER_add_read (struct GNUNET_SCHEDULER_Handle *sched,
349                            int run_on_shutdown,
350                            enum GNUNET_SCHEDULER_Priority prio,
351                            GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
352                            struct GNUNET_TIME_Relative delay,
353                            int rfd, GNUNET_SCHEDULER_Task main, void *cls);
354
355
356 /**
357  * Schedule a new task to be run with a specified delay or when the
358  * specified file descriptor is ready for writing.  The delay can be
359  * used as a timeout on the socket being ready.  The task will be
360  * scheduled for execution once either the delay has expired or the
361  * socket operation is ready.
362  *
363  * @param sched scheduler to use
364  * @param run_on_shutdown run on shutdown? Set this
365  *        argument to GNUNET_NO to skip this task if
366  *        the user requested process termination.
367  * @param prio how important is this task?
368  * @param prerequisite_task run this task after the task with the given
369  *        task identifier completes (and any of our other
370  *        conditions, such as delay, read or write-readyness
371  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_PREREQUISITE_TASK to not have any dependency
372  *        on completion of other tasks.
373  * @param delay how long should we wait? Use  GNUNET_TIME_UNIT_FOREVER_REL for "forever"
374  * @param wfd write file-descriptor
375  * @param main main function of the task
376  * @param cls closure of task
377  * @return unique task identifier for the job
378  *         only valid until "main" is started!
379  */
380 GNUNET_SCHEDULER_TaskIdentifier
381 GNUNET_SCHEDULER_add_write (struct GNUNET_SCHEDULER_Handle *sched,
382                             int run_on_shutdown,
383                             enum GNUNET_SCHEDULER_Priority prio,
384                             GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
385                             struct GNUNET_TIME_Relative delay,
386                             int wfd, GNUNET_SCHEDULER_Task main, void *cls);
387
388
389 /**
390  * Schedule a new task to be run with a specified delay or when any of
391  * the specified file descriptor sets is ready.  The delay can be used
392  * as a timeout on the socket(s) being ready.  The task will be
393  * scheduled for execution once either the delay has expired or any of
394  * the socket operations is ready.  This is the most general
395  * function of the "add" family.  Note that the "prerequisite_task"
396  * must be satisfied in addition to any of the other conditions.  In
397  * other words, the task will be started when
398  * <code>
399  * (prerequisite-run)
400  * && (delay-ready
401  *     || any-rs-ready
402  *     || any-ws-ready
403  *     || (shutdown-active && run-on-shutdown) )
404  * </code>
405  *
406  * @param sched scheduler to use
407  * @param run_on_shutdown run on shutdown?  Set this
408  *        argument to GNUNET_NO to skip this task if
409  *        the user requested process termination.
410  * @param prio how important is this task?
411  * @param prerequisite_task run this task after the task with the given
412  *        task identifier completes (and any of our other
413  *        conditions, such as delay, read or write-readyness
414  *        are satisfied).  Use GNUNET_SCHEDULER_NO_PREREQUISITE_TASK to not have any dependency
415  *        on completion of other tasks.
416  * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever"
417  * @param nfds highest-numbered file descriptor in any of the two sets plus one
418  * @param rs set of file descriptors we want to read (can be NULL)
419  * @param ws set of file descriptors we want to write (can be NULL)
420  * @param main main function of the task
421  * @param cls closure of task
422  * @return unique task identifier for the job
423  *         only valid until "main" is started!
424  */
425 GNUNET_SCHEDULER_TaskIdentifier
426 GNUNET_SCHEDULER_add_select (struct GNUNET_SCHEDULER_Handle *sched,
427                              int run_on_shutdown,
428                              enum GNUNET_SCHEDULER_Priority prio,
429                              GNUNET_SCHEDULER_TaskIdentifier
430                              prerequisite_task,
431                              struct GNUNET_TIME_Relative delay,
432                              int nfds, const fd_set * rs, const fd_set * ws,
433                              GNUNET_SCHEDULER_Task main, void *cls);
434
435 #if 0                           /* keep Emacsens' auto-indent happy */
436 {
437 #endif
438 #ifdef __cplusplus
439 }
440 #endif
441
442 #endif