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