-fix
[oweals/gnunet.git] / src / include / gnunet_scheduler_lib.h
1 /*
2       This file is part of GNUnet
3       (C) 2009, 2011 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 /**
39  * Opaque reference to a task.
40  */
41 typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier;
42
43
44 /**
45  * Constant used to indicate that the scheduled
46  * task has no others as prerequisites.
47  */
48 #define GNUNET_SCHEDULER_NO_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0)
49
50 /**
51  * Reasons why the schedule may have triggered
52  * the task now.
53  */
54 enum GNUNET_SCHEDULER_Reason
55 {
56   /**
57    * This is the very first task run during startup.
58    */
59   GNUNET_SCHEDULER_REASON_STARTUP = 0,
60
61   /**
62    * We are shutting down and are running all shutdown-related tasks
63    * (regardless of timeout, etc.).
64    */
65   GNUNET_SCHEDULER_REASON_SHUTDOWN = 1,
66
67   /**
68    * The specified timeout has expired.
69    * (also set if the delay given was 0).
70    */
71   GNUNET_SCHEDULER_REASON_TIMEOUT = 2,
72
73   /**
74    * The reading socket is ready.
75    */
76   GNUNET_SCHEDULER_REASON_READ_READY = 4,
77
78   /**
79    * The writing socket is ready.
80    */
81   GNUNET_SCHEDULER_REASON_WRITE_READY = 8,
82
83   /**
84    * The prerequisite task is done.
85    */
86   GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16
87 };
88
89
90 /**
91  * Valid task priorities.  Use these, do not
92  * pass random integers!
93  */
94 enum GNUNET_SCHEDULER_Priority
95 {
96   /**
97    * Run with the same priority as the current job.
98    */
99   GNUNET_SCHEDULER_PRIORITY_KEEP = 0,
100
101   /**
102    * Run when otherwise idle.
103    */
104   GNUNET_SCHEDULER_PRIORITY_IDLE = 1,
105
106   /**
107    * Run as background job (higher than idle,
108    * lower than default).
109    */
110   GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2,
111
112   /**
113    * Run with the default priority (normal
114    * P2P operations).  Any task that is scheduled
115    * without an explicit priority being specified
116    * will run with this priority.
117    */
118   GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3,
119
120   /**
121    * Run with high priority (important requests).
122    * Higher than DEFAULT.
123    */
124   GNUNET_SCHEDULER_PRIORITY_HIGH = 4,
125
126   /**
127    * Run with priority for interactive tasks.
128    * Higher than "HIGH".
129    */
130   GNUNET_SCHEDULER_PRIORITY_UI = 5,
131
132   /**
133    * Run with priority for urgent tasks.  Use
134    * for things like aborts and shutdowns that
135    * need to preempt "UI"-level tasks.
136    * Higher than "UI".
137    */
138   GNUNET_SCHEDULER_PRIORITY_URGENT = 6,
139
140   /**
141    * This is an internal priority level that is only used for tasks
142    * that are being triggered due to shutdown (they have automatically
143    * highest priority).  User code must not use this priority level
144    * directly.  Tasks run with this priority level that internally
145    * schedule other tasks will see their original priority level
146    * be inherited (unless otherwise specified).
147    */
148   GNUNET_SCHEDULER_PRIORITY_SHUTDOWN = 7,
149
150   /**
151    * Number of priorities (must be the last priority).
152    * This priority must not be used by clients.
153    */
154   GNUNET_SCHEDULER_PRIORITY_COUNT = 8
155 };
156
157 #include "gnunet_time_lib.h"
158 #include "gnunet_network_lib.h"
159
160
161 /**
162  * Context information passed to each scheduler task.
163  */
164 struct GNUNET_SCHEDULER_TaskContext
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 struct GNUNET_NETWORK_FDSet *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 struct GNUNET_NETWORK_FDSet *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 GNUNET_SCHEDULER_TaskContext
196                                        * tc);
197
198
199 /**
200  * Signature of the select function used by the scheduler.
201  * GNUNET_NETWORK_socket_select matches it.
202  *
203  * @param cls closure
204  * @param rfds set of sockets to be checked for readability
205  * @param wfds set of sockets to be checked for writability
206  * @param efds set of sockets to be checked for exceptions
207  * @param timeout relative value when to return
208  * @return number of selected sockets, GNUNET_SYSERR on error
209  */
210 typedef int (*GNUNET_SCHEDULER_select) (void *cls,
211                                         struct GNUNET_NETWORK_FDSet * rfds,
212                                         struct GNUNET_NETWORK_FDSet * wfds,
213                                         struct GNUNET_NETWORK_FDSet * efds,
214                                         struct GNUNET_TIME_Relative timeout);
215 /**
216  * Initialize and run scheduler.  This function will return when all
217  * tasks have completed.  On systems with signals, receiving a SIGTERM
218  * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown"
219  * to be run after the active task is complete.  As a result, SIGTERM
220  * causes all active tasks to be scheduled with reason
221  * "GNUNET_SCHEDULER_REASON_SHUTDOWN".  (However, tasks added
222  * afterwards will execute normally!).  Note that any particular
223  * signal will only shut down one scheduler; applications should
224  * always only create a single scheduler.
225  *
226  * @param task task to run first (and immediately)
227  * @param task_cls closure of task
228  */
229 void
230 GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls);
231
232
233 /**
234  * Request the shutdown of a scheduler.  Marks all currently
235  * pending tasks as ready because of shutdown.  This will
236  * cause all tasks to run (as soon as possible, respecting
237  * priorities and prerequisite tasks).  Note that tasks
238  * scheduled AFTER this call may still be delayed arbitrarily.
239  */
240 void
241 GNUNET_SCHEDULER_shutdown ();
242
243
244 /**
245  * Get information about the current load of this scheduler.  Use this
246  * function to determine if an elective task should be added or simply
247  * dropped (if the decision should be made based on the number of
248  * tasks ready to run).
249  *
250  * * @param p priority-level to query, use KEEP to query the level
251  *          of the current task, use COUNT to get the sum over
252  *          all priority levels
253  * @return number of tasks pending right now
254  */
255 unsigned int
256 GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p);
257
258
259 /**
260  * Obtain the reason code for why the current task was
261  * started.  Will return the same value as
262  * the GNUNET_SCHEDULER_TaskContext's reason field.
263  *
264  * * @return reason(s) why the current task is run
265  */
266 enum GNUNET_SCHEDULER_Reason
267 GNUNET_SCHEDULER_get_reason (void);
268
269
270 /**
271  * Cancel the task with the specified identifier.
272  * The task must not yet have run.
273  *
274  * * @param task id of the task to cancel
275  * @return the closure of the callback of the cancelled task
276  */
277 void *
278 GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task);
279
280
281 /**
282  * Continue the current execution with the given function.  This is
283  * similar to the other "add" functions except that there is no delay
284  * and the reason code can be specified.
285  *
286  * * @param task main function of the task
287  * @param task_cls closure of task
288  * @param reason reason for task invocation
289  */
290 void
291 GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls,
292                                    enum GNUNET_SCHEDULER_Reason reason);
293
294
295 /**
296  * Continue the current execution with the given function.  This is
297  * similar to the other "add" functions except that there is no delay
298  * and the reason code can be specified.
299  *
300  * @param task main function of the task
301  * @param task_cls closure for 'main'
302  * @param reason reason for task invocation
303  * @param priority priority to use for the task
304  */
305 void
306 GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, void *task_cls,
307                                                  enum GNUNET_SCHEDULER_Reason reason,
308                                                  enum GNUNET_SCHEDULER_Priority priority);
309
310
311 /**
312  * Schedule a new task to be run after the specified prerequisite task
313  * has completed. It will be run with DEFAULT priority.
314  *
315  * * @param prerequisite_task run this task after the task with the given
316  *        task identifier completes (and any of our other
317  *        conditions, such as delay, read or write-readiness
318  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_TASK to not have any dependency
319  *        on completion of other tasks (this will cause the task to run as
320  *        soon as possible).
321  * @param task main function of the task
322  * @param task_cls closure of task
323  * @return unique task identifier for the job
324  *         only valid until "task" is started!
325  */
326 GNUNET_SCHEDULER_TaskIdentifier
327 GNUNET_SCHEDULER_add_after (GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
328                             GNUNET_SCHEDULER_Task task, void *task_cls);
329
330
331 /**
332  * Schedule a new task to be run with a specified priority.
333  *
334  * * @param prio how important is the new task?
335  * @param task main function of the task
336  * @param task_cls closure of task
337  * @return unique task identifier for the job
338  *         only valid until "task" is started!
339  */
340 GNUNET_SCHEDULER_TaskIdentifier
341 GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio,
342                                     GNUNET_SCHEDULER_Task task, void *task_cls);
343
344
345 /**
346  * Schedule a new task to be run as soon as possible. The task
347  * will be run with the DEFAULT priority.
348  *
349  * * @param task main function of the task
350  * @param task_cls closure of task
351  * @return unique task identifier for the job
352  *         only valid until "task" is started!
353  */
354 GNUNET_SCHEDULER_TaskIdentifier
355 GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls);
356
357
358 /**
359  * Schedule a new task to be run as soon as possible with the
360  * (transitive) ignore-shutdown flag either explicitly set or
361  * explicitly enabled.  This task (and all tasks created from it,
362  * other than by another call to this function) will either count or
363  * not count for the 'lifeness' of the process.  This API is only
364  * useful in a few special cases.
365  *
366  * @param lifeness GNUNET_YES if the task counts for lifeness, GNUNET_NO if not.
367  * @param task main function of the task
368  * @param task_cls closure of task
369  * @return unique task identifier for the job
370  *         only valid until "task" is started!
371  */
372 GNUNET_SCHEDULER_TaskIdentifier
373 GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
374                                         GNUNET_SCHEDULER_Task task,
375                                         void *task_cls);
376
377
378 /**
379  * Schedule a new task to be run with a specified delay.  The task
380  * will be scheduled for execution once the delay has expired. It
381  * will be run with the DEFAULT priority.
382  *
383  * * @param delay when should this operation time out? Use
384  *        GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
385  * @param task main function of the task
386  * @param task_cls closure of task
387  * @return unique task identifier for the job
388  *         only valid until "task" is started!
389  */
390 GNUNET_SCHEDULER_TaskIdentifier
391 GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
392                               GNUNET_SCHEDULER_Task task, void *task_cls);
393
394
395 /**
396  * Schedule a new task to be run with a specified delay.  The task
397  * will be scheduled for execution once the delay has expired.
398  *
399  * @param delay when should this operation time out? Use
400  *        GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
401  * @param priority priority to use for the task
402  * @param task main function of the task
403  * @param task_cls closure of task
404  * @return unique task identifier for the job
405  *         only valid until "task" is started!
406  */
407 GNUNET_SCHEDULER_TaskIdentifier
408 GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
409                                             enum GNUNET_SCHEDULER_Priority priority,
410                                             GNUNET_SCHEDULER_Task task, void *task_cls);
411
412
413 /**
414  * Schedule a new task to be run with a specified delay or when the
415  * specified file descriptor is ready for reading.  The delay can be
416  * used as a timeout on the socket being ready.  The task will be
417  * scheduled for execution once either the delay has expired or the
418  * socket operation is ready.  It will be run with the DEFAULT priority.
419  *
420  * * @param delay when should this operation time out? Use
421  *        GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
422  * @param rfd read file-descriptor
423  * @param task main function of the task
424  * @param task_cls closure of task
425  * @return unique task identifier for the job
426  *         only valid until "task" is started!
427  */
428 GNUNET_SCHEDULER_TaskIdentifier
429 GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
430                                struct GNUNET_NETWORK_Handle *rfd,
431                                GNUNET_SCHEDULER_Task task, void *task_cls);
432
433
434 /**
435  * Schedule a new task to be run with a specified delay or when the
436  * specified file descriptor is ready for writing.  The delay can be
437  * used as a timeout on the socket being ready.  The task will be
438  * scheduled for execution once either the delay has expired or the
439  * socket operation is ready.  It will be run with the DEFAULT priority.
440  *
441  * * @param delay when should this operation time out? Use
442  *        GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
443  * @param wfd write file-descriptor
444  * @param task main function of the task
445  * @param task_cls closure of task
446  * @return unique task identifier for the job
447  *         only valid until "task" is started!
448  */
449 GNUNET_SCHEDULER_TaskIdentifier
450 GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
451                                 struct GNUNET_NETWORK_Handle *wfd,
452                                 GNUNET_SCHEDULER_Task task, void *task_cls);
453
454
455 /**
456  * Schedule a new task to be run with a specified delay or when the
457  * specified file descriptor is ready for reading.  The delay can be
458  * used as a timeout on the socket being ready.  The task will be
459  * scheduled for execution once either the delay has expired or the
460  * socket operation is ready. It will be run with the DEFAULT priority.
461  *
462  * * @param delay when should this operation time out? Use
463  *        GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
464  * @param rfd read file-descriptor
465  * @param task main function of the task
466  * @param task_cls closure of task
467  * @return unique task identifier for the job
468  *         only valid until "task" is started!
469  */
470 GNUNET_SCHEDULER_TaskIdentifier
471 GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
472                                 const struct GNUNET_DISK_FileHandle *rfd,
473                                 GNUNET_SCHEDULER_Task task, void *task_cls);
474
475
476 /**
477  * Schedule a new task to be run with a specified delay or when the
478  * specified file descriptor is ready for writing.  The delay can be
479  * used as a timeout on the socket being ready.  The task will be
480  * scheduled for execution once either the delay has expired or the
481  * socket operation is ready. It will be run with the DEFAULT priority.
482  *
483  * * @param delay when should this operation time out? Use
484  *        GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
485  * @param wfd write file-descriptor
486  * @param task main function of the task
487  * @param task_cls closure of task
488  * @return unique task identifier for the job
489  *         only valid until "task" is started!
490  */
491 GNUNET_SCHEDULER_TaskIdentifier
492 GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
493                                  const struct GNUNET_DISK_FileHandle *wfd,
494                                  GNUNET_SCHEDULER_Task task, void *task_cls);
495
496
497 /**
498  * Schedule a new task to be run with a specified delay or when any of
499  * the specified file descriptor sets is ready.  The delay can be used
500  * as a timeout on the socket(s) being ready.  The task will be
501  * scheduled for execution once either the delay has expired or any of
502  * the socket operations is ready.  This is the most general
503  * function of the "add" family.  Note that the "prerequisite_task"
504  * must be satisfied in addition to any of the other conditions.  In
505  * other words, the task will be started when
506  * <code>
507  * (prerequisite-run)
508  * && (delay-ready
509  *     || any-rs-ready
510  *     || any-ws-ready
511  *     || shutdown-active)
512  * </code>
513  *
514  * * @param prio how important is this task?
515  * @param prerequisite_task run this task after the task with the given
516  *        task identifier completes (and any of our other
517  *        conditions, such as delay, read or write-readiness
518  *        are satisfied).  Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
519  *        on completion of other tasks.
520  * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever",
521  *        which means that the task will only be run after we receive SIGTERM
522  * @param rs set of file descriptors we want to read (can be NULL)
523  * @param ws set of file descriptors we want to write (can be NULL)
524  * @param task main function of the task
525  * @param task_cls closure of task
526  * @return unique task identifier for the job
527  *         only valid until "task" is started!
528  */
529 GNUNET_SCHEDULER_TaskIdentifier
530 GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
531                              GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
532                              struct GNUNET_TIME_Relative delay,
533                              const struct GNUNET_NETWORK_FDSet *rs,
534                              const struct GNUNET_NETWORK_FDSet *ws,
535                              GNUNET_SCHEDULER_Task task, void *task_cls);
536
537 /**
538  * Sets the select function to use in the scheduler (scheduler_select).
539  *
540  * @param new_select new select function to use (NULL to reset to default)
541  * @param new_select_cls closure for 'new_select'
542  */
543 void
544 GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select,
545                              void *new_select_cls);
546
547
548 #if 0                           /* keep Emacsens' auto-indent happy */
549 {
550 #endif
551 #ifdef __cplusplus
552 }
553 #endif
554
555 #endif