2 This file is part of GNUnet
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
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.
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.
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.
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)
29 #ifndef GNUNET_SCHEDULER_LIB_H
30 #define GNUNET_SCHEDULER_LIB_H
37 #if 0 /* keep Emacsens' auto-indent happy */
43 * Opaque reference to a task.
45 typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier;
49 * Constant used to indicate that the scheduled
50 * task has no others as prerequisites.
52 #define GNUNET_SCHEDULER_NO_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0)
55 * Reasons why the schedule may have triggered
58 enum GNUNET_SCHEDULER_Reason
61 * This is the very first task run during startup.
63 GNUNET_SCHEDULER_REASON_STARTUP = 0,
66 * We are shutting down and are running all shutdown-related tasks
67 * (regardless of timeout, etc.).
69 GNUNET_SCHEDULER_REASON_SHUTDOWN = 1,
72 * The specified timeout has expired.
73 * (also set if the delay given was 0).
75 GNUNET_SCHEDULER_REASON_TIMEOUT = 2,
78 * The reading socket is ready.
80 GNUNET_SCHEDULER_REASON_READ_READY = 4,
83 * The writing socket is ready.
85 GNUNET_SCHEDULER_REASON_WRITE_READY = 8,
88 * The prerequisite task is done.
90 GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16
95 * Valid task priorities. Use these, do not
96 * pass random integers!
98 enum GNUNET_SCHEDULER_Priority
101 * Run with the same priority as the current job.
103 GNUNET_SCHEDULER_PRIORITY_KEEP = 0,
106 * Run when otherwise idle.
108 GNUNET_SCHEDULER_PRIORITY_IDLE = 1,
111 * Run as background job (higher than idle,
112 * lower than default).
114 GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2,
117 * Run with the default priority (normal
118 * P2P operations). Any task that is scheduled
119 * without an explicit priority being specified
120 * will run with this priority.
122 GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3,
125 * Run with high priority (important requests).
126 * Higher than DEFAULT.
128 GNUNET_SCHEDULER_PRIORITY_HIGH = 4,
131 * Run with priority for interactive tasks.
132 * Higher than "HIGH".
134 GNUNET_SCHEDULER_PRIORITY_UI = 5,
137 * Run with priority for urgent tasks. Use
138 * for things like aborts and shutdowns that
139 * need to preempt "UI"-level tasks.
142 GNUNET_SCHEDULER_PRIORITY_URGENT = 6,
145 * This is an internal priority level that is only used for tasks
146 * that are being triggered due to shutdown (they have automatically
147 * highest priority). User code must not use this priority level
148 * directly. Tasks run with this priority level that internally
149 * schedule other tasks will see their original priority level
150 * be inherited (unless otherwise specified).
152 GNUNET_SCHEDULER_PRIORITY_SHUTDOWN = 7,
155 * Number of priorities (must be the last priority).
156 * This priority must not be used by clients.
158 GNUNET_SCHEDULER_PRIORITY_COUNT = 8
161 #include "gnunet_time_lib.h"
162 #include "gnunet_network_lib.h"
166 * Context information passed to each scheduler task.
168 struct GNUNET_SCHEDULER_TaskContext
171 * Reason why the task is run now
173 enum GNUNET_SCHEDULER_Reason reason;
176 * Set of file descriptors ready for reading;
177 * note that additional bits may be set
178 * that were not in the original request
180 const struct GNUNET_NETWORK_FDSet *read_ready;
183 * Set of file descriptors ready for writing;
184 * note that additional bits may be set
185 * that were not in the original request.
187 const struct GNUNET_NETWORK_FDSet *write_ready;
193 * Signature of the main function of a task.
196 * @param tc context information (why was this task triggered now)
198 typedef void (*GNUNET_SCHEDULER_Task) (void *cls,
199 const struct GNUNET_SCHEDULER_TaskContext
204 * Signature of the select function used by the scheduler.
205 * #GNUNET_NETWORK_socket_select matches it.
208 * @param rfds set of sockets to be checked for readability
209 * @param wfds set of sockets to be checked for writability
210 * @param efds set of sockets to be checked for exceptions
211 * @param timeout relative value when to return
212 * @return number of selected sockets, #GNUNET_SYSERR on error
214 typedef int (*GNUNET_SCHEDULER_select) (void *cls,
215 struct GNUNET_NETWORK_FDSet *rfds,
216 struct GNUNET_NETWORK_FDSet *wfds,
217 struct GNUNET_NETWORK_FDSet *efds,
218 struct GNUNET_TIME_Relative timeout);
222 * Initialize and run scheduler. This function will return when all
223 * tasks have completed. On systems with signals, receiving a SIGTERM
224 * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown
225 * to be run after the active task is complete. As a result, SIGTERM
226 * causes all active tasks to be scheduled with reason
227 * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added
228 * afterwards will execute normally!). Note that any particular
229 * signal will only shut down one scheduler; applications should
230 * always only create a single scheduler.
232 * @param task task to run first (and immediately)
233 * @param task_cls closure of task
236 GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls);
240 * Request the shutdown of a scheduler. Marks all currently
241 * pending tasks as ready because of shutdown. This will
242 * cause all tasks to run (as soon as possible, respecting
243 * priorities and prerequisite tasks). Note that tasks
244 * scheduled AFTER this call may still be delayed arbitrarily.
247 GNUNET_SCHEDULER_shutdown (void);
251 * Get information about the current load of this scheduler. Use this
252 * function to determine if an elective task should be added or simply
253 * dropped (if the decision should be made based on the number of
254 * tasks ready to run).
256 * @param p priority-level to query, use KEEP to query the level
257 * of the current task, use COUNT to get the sum over
258 * all priority levels
259 * @return number of tasks pending right now
262 GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p);
266 * Obtain the reason code for why the current task was
267 * started. Will return the same value as
268 * the GNUNET_SCHEDULER_TaskContext's reason field.
270 * @return reason(s) why the current task is run
272 enum GNUNET_SCHEDULER_Reason
273 GNUNET_SCHEDULER_get_reason (void);
277 * Cancel the task with the specified identifier.
278 * The task must not yet have run.
280 * @param task id of the task to cancel
281 * @return the closure of the callback of the cancelled task
284 GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task);
288 * Continue the current execution with the given function. This is
289 * similar to the other "add" functions except that there is no delay
290 * and the reason code can be specified.
292 * @param task main function of the task
293 * @param task_cls closure of task
294 * @param reason reason for task invocation
297 GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls,
298 enum GNUNET_SCHEDULER_Reason reason);
302 * Continue the current execution with the given function. This is
303 * similar to the other "add" functions except that there is no delay
304 * and the reason code can be specified.
306 * @param task main function of the task
307 * @param task_cls closure for @a task
308 * @param reason reason for task invocation
309 * @param priority priority to use for the task
312 GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, void *task_cls,
313 enum GNUNET_SCHEDULER_Reason reason,
314 enum GNUNET_SCHEDULER_Priority priority);
318 * Schedule a new task to be run with a specified priority.
320 * @param prio how important is the new task?
321 * @param task main function of the task
322 * @param task_cls closure of @a task
323 * @return unique task identifier for the job
324 * only valid until @a task is started!
326 GNUNET_SCHEDULER_TaskIdentifier
327 GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio,
328 GNUNET_SCHEDULER_Task task, void *task_cls);
332 * Schedule a new task to be run as soon as possible. Note that this
333 * does not guarantee that this will be the next task that is being
334 * run, as other tasks with higher priority (or that are already ready
335 * to run) might get to run first. Just as with delays, clients must
336 * not rely on any particular order of execution between tasks
337 * scheduled concurrently.
339 * The task will be run with the DEFAULT priority.
341 * @param task main function of the task
342 * @param task_cls closure of @a task
343 * @return unique task identifier for the job
344 * only valid until @a task is started!
346 GNUNET_SCHEDULER_TaskIdentifier
347 GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls);
351 * Schedule a new task to be run as soon as possible with the
352 * (transitive) ignore-shutdown flag either explicitly set or
353 * explicitly enabled. This task (and all tasks created from it,
354 * other than by another call to this function) will either count or
355 * not count for the 'lifeness' of the process. This API is only
356 * useful in a few special cases.
358 * @param lifeness #GNUNET_YES if the task counts for lifeness, #GNUNET_NO if not.
359 * @param task main function of the task
360 * @param task_cls closure of @a task
361 * @return unique task identifier for the job
362 * only valid until @a task is started!
364 GNUNET_SCHEDULER_TaskIdentifier
365 GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
366 GNUNET_SCHEDULER_Task task,
371 * Schedule a new task to be run with a specified delay. The task
372 * will be scheduled for execution once the delay has expired. It
373 * will be run with the DEFAULT priority.
375 * * @param delay when should this operation time out? Use
376 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
377 * @param task main function of the task
378 * @param task_cls closure of @a task
379 * @return unique task identifier for the job
380 * only valid until @a task is started!
382 GNUNET_SCHEDULER_TaskIdentifier
383 GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
384 GNUNET_SCHEDULER_Task task, void *task_cls);
388 * Schedule a new task to be run with a specified delay. The task
389 * will be scheduled for execution once the delay has expired.
391 * @param delay when should this operation time out? Use
392 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
393 * @param priority priority to use for the task
394 * @param task main function of the task
395 * @param task_cls closure of @a task
396 * @return unique task identifier for the job
397 * only valid until @a task is started!
399 GNUNET_SCHEDULER_TaskIdentifier
400 GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
401 enum GNUNET_SCHEDULER_Priority priority,
402 GNUNET_SCHEDULER_Task task, void *task_cls);
406 * Schedule a new task to be run with a specified delay or when the
407 * specified file descriptor is ready for reading. The delay can be
408 * used as a timeout on the socket being ready. The task will be
409 * scheduled for execution once either the delay has expired or the
410 * socket operation is ready. It will be run with the DEFAULT priority.
412 * * @param delay when should this operation time out? Use
413 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
414 * @param rfd read file-descriptor
415 * @param task main function of the task
416 * @param task_cls closure of @a task
417 * @return unique task identifier for the job
418 * only valid until @a task is started!
420 GNUNET_SCHEDULER_TaskIdentifier
421 GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
422 struct GNUNET_NETWORK_Handle *rfd,
423 GNUNET_SCHEDULER_Task task, void *task_cls);
427 * Schedule a new task to be run with a specified priority and to be
428 * run after the specified delay or when the specified file descriptor
429 * is ready for reading. The delay can be used as a timeout on the
430 * socket being ready. The task will be scheduled for execution once
431 * either the delay has expired or the socket operation is ready. It
432 * will be run with the DEFAULT priority.
434 * @param delay when should this operation time out? Use
435 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
436 * @param priority priority to use for the task
437 * @param rfd read file-descriptor
438 * @param task main function of the task
439 * @param task_cls closure of @a task
440 * @return unique task identifier for the job
441 * only valid until @a task is started!
443 GNUNET_SCHEDULER_TaskIdentifier
444 GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
445 enum GNUNET_SCHEDULER_Priority priority,
446 struct GNUNET_NETWORK_Handle *rfd,
447 GNUNET_SCHEDULER_Task task, void *task_cls);
451 * Schedule a new task to be run with a specified delay or when the
452 * specified file descriptor is ready for writing. The delay can be
453 * used as a timeout on the socket being ready. The task will be
454 * scheduled for execution once either the delay has expired or the
455 * socket operation is ready. It will be run with the DEFAULT priority.
457 * * @param delay when should this operation time out? Use
458 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
459 * @param wfd write file-descriptor
460 * @param task main function of the task
461 * @param task_cls closure of @a task
462 * @return unique task identifier for the job
463 * only valid until @a task is started!
465 GNUNET_SCHEDULER_TaskIdentifier
466 GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
467 struct GNUNET_NETWORK_Handle *wfd,
468 GNUNET_SCHEDULER_Task task, void *task_cls);
472 * Schedule a new task to be run with a specified delay or when the
473 * specified file descriptor is ready. The delay can be
474 * used as a timeout on the socket being ready. The task will be
475 * scheduled for execution once either the delay has expired or the
476 * socket operation is ready.
478 * @param delay when should this operation time out? Use
479 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
480 * @param priority priority of the task
481 * @param fd file-descriptor
482 * @param on_read whether to poll the file-descriptor for readability
483 * @param on_write whether to poll the file-descriptor for writability
484 * @param task main function of the task
485 * @param task_cls closure of task
486 * @return unique task identifier for the job
487 * only valid until "task" is started!
489 GNUNET_SCHEDULER_TaskIdentifier
490 GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
491 enum GNUNET_SCHEDULER_Priority priority,
492 struct GNUNET_NETWORK_Handle *fd,
493 bool on_read, bool on_write,
494 GNUNET_SCHEDULER_Task task, void *task_cls);
497 * Schedule a new task to be run with a specified delay or when the
498 * specified file descriptor is ready for reading. The delay can be
499 * used as a timeout on the socket being ready. The task will be
500 * scheduled for execution once either the delay has expired or the
501 * socket operation is ready. It will be run with the DEFAULT priority.
503 * * @param delay when should this operation time out? Use
504 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
505 * @param rfd read file-descriptor
506 * @param task main function of the task
507 * @param task_cls closure of @a task
508 * @return unique task identifier for the job
509 * only valid until "task" is started!
511 GNUNET_SCHEDULER_TaskIdentifier
512 GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
513 const struct GNUNET_DISK_FileHandle *rfd,
514 GNUNET_SCHEDULER_Task task, void *task_cls);
518 * Schedule a new task to be run with a specified delay or when the
519 * specified file descriptor is ready for writing. The delay can be
520 * used as a timeout on the socket being ready. The task will be
521 * scheduled for execution once either the delay has expired or the
522 * socket operation is ready. It will be run with the DEFAULT priority.
524 * * @param delay when should this operation time out? Use
525 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
526 * @param wfd write file-descriptor
527 * @param task main function of the task
528 * @param task_cls closure of @a task
529 * @return unique task identifier for the job
530 * only valid until @a task is started!
532 GNUNET_SCHEDULER_TaskIdentifier
533 GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
534 const struct GNUNET_DISK_FileHandle *wfd,
535 GNUNET_SCHEDULER_Task task, void *task_cls);
539 * Schedule a new task to be run with a specified delay or when the
540 * specified file descriptor is ready. The delay can be
541 * used as a timeout on the socket being ready. The task will be
542 * scheduled for execution once either the delay has expired or the
543 * socket operation is ready.
545 * @param delay when should this operation time out? Use
546 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
547 * @param priority priority of the task
548 * @param fd file-descriptor
549 * @param on_read whether to poll the file-descriptor for readability
550 * @param on_write whether to poll the file-descriptor for writability
551 * @param task main function of the task
552 * @param task_cls closure of task
553 * @return unique task identifier for the job
554 * only valid until "task" is started!
556 GNUNET_SCHEDULER_TaskIdentifier
557 GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
558 enum GNUNET_SCHEDULER_Priority priority,
559 const struct GNUNET_DISK_FileHandle *fd,
560 bool on_read, bool on_write,
561 GNUNET_SCHEDULER_Task task, void *task_cls);
565 * Schedule a new task to be run with a specified delay or when any of
566 * the specified file descriptor sets is ready. The delay can be used
567 * as a timeout on the socket(s) being ready. The task will be
568 * scheduled for execution once either the delay has expired or any of
569 * the socket operations is ready. This is the most general
570 * function of the "add" family. Note that the "prerequisite_task"
571 * must be satisfied in addition to any of the other conditions. In
572 * other words, the task will be started when
578 * || shutdown-active)
581 * @param prio how important is this task?
582 * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever",
583 * which means that the task will only be run after we receive SIGTERM
584 * @param rs set of file descriptors we want to read (can be NULL)
585 * @param ws set of file descriptors we want to write (can be NULL)
586 * @param task main function of the task
587 * @param task_cls closure of @a task
588 * @return unique task identifier for the job
589 * only valid until "task" is started!
591 GNUNET_SCHEDULER_TaskIdentifier
592 GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
593 struct GNUNET_TIME_Relative delay,
594 const struct GNUNET_NETWORK_FDSet *rs,
595 const struct GNUNET_NETWORK_FDSet *ws,
596 GNUNET_SCHEDULER_Task task, void *task_cls);
599 * Sets the select function to use in the scheduler (scheduler_select).
601 * @param new_select new select function to use (NULL to reset to default)
602 * @param new_select_cls closure for 'new_select'
605 GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select,
606 void *new_select_cls);
609 /** @} */ /* end of group scheduler */
611 #if 0 /* keep Emacsens' auto-indent happy */