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