2 This file is part of GNUnet
3 (C) 2009, 2011 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 2, 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
27 #ifndef GNUNET_SCHEDULER_LIB_H
28 #define GNUNET_SCHEDULER_LIB_H
33 #if 0 /* keep Emacsens' auto-indent happy */
39 * Opaque reference to a task.
41 typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier;
45 * Constant used to indicate that the scheduled
46 * task has no others as prerequisites.
48 #define GNUNET_SCHEDULER_NO_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0)
51 * Reasons why the schedule may have triggered
54 enum GNUNET_SCHEDULER_Reason
57 * This is the very first task run during startup.
59 GNUNET_SCHEDULER_REASON_STARTUP = 0,
62 * We are shutting down and are running all shutdown-related tasks
63 * (regardless of timeout, etc.).
65 GNUNET_SCHEDULER_REASON_SHUTDOWN = 1,
68 * The specified timeout has expired.
69 * (also set if the delay given was 0).
71 GNUNET_SCHEDULER_REASON_TIMEOUT = 2,
74 * The reading socket is ready.
76 GNUNET_SCHEDULER_REASON_READ_READY = 4,
79 * The writing socket is ready.
81 GNUNET_SCHEDULER_REASON_WRITE_READY = 8,
84 * The prerequisite task is done.
86 GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16
91 * Valid task priorities. Use these, do not
92 * pass random integers!
94 enum GNUNET_SCHEDULER_Priority
97 * Run with the same priority as the current job.
99 GNUNET_SCHEDULER_PRIORITY_KEEP = 0,
102 * Run when otherwise idle.
104 GNUNET_SCHEDULER_PRIORITY_IDLE = 1,
107 * Run as background job (higher than idle,
108 * lower than default).
110 GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2,
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.
118 GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3,
121 * Run with high priority (important requests).
122 * Higher than DEFAULT.
124 GNUNET_SCHEDULER_PRIORITY_HIGH = 4,
127 * Run with priority for interactive tasks.
128 * Higher than "HIGH".
130 GNUNET_SCHEDULER_PRIORITY_UI = 5,
133 * Run with priority for urgent tasks. Use
134 * for things like aborts and shutdowns that
135 * need to preempt "UI"-level tasks.
138 GNUNET_SCHEDULER_PRIORITY_URGENT = 6,
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).
148 GNUNET_SCHEDULER_PRIORITY_SHUTDOWN = 7,
151 * Number of priorities (must be the last priority).
152 * This priority must not be used by clients.
154 GNUNET_SCHEDULER_PRIORITY_COUNT = 8
157 #include "gnunet_time_lib.h"
158 #include "gnunet_network_lib.h"
162 * Context information passed to each scheduler task.
164 struct GNUNET_SCHEDULER_TaskContext
167 * Reason why the task is run now
169 enum GNUNET_SCHEDULER_Reason reason;
172 * Set of file descriptors ready for reading;
173 * note that additional bits may be set
174 * that were not in the original request
176 const struct GNUNET_NETWORK_FDSet *read_ready;
179 * Set of file descriptors ready for writing;
180 * note that additional bits may be set
181 * that were not in the original request.
183 const struct GNUNET_NETWORK_FDSet *write_ready;
189 * Signature of the main function of a task.
192 * @param tc context information (why was this task triggered now)
194 typedef void (*GNUNET_SCHEDULER_Task) (void *cls,
195 const struct GNUNET_SCHEDULER_TaskContext
200 * Signature of the select function used by the scheduler.
201 * GNUNET_NETWORK_socket_select matches it.
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
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);
218 * Initialize and run scheduler. This function will return when all
219 * tasks have completed. On systems with signals, receiving a SIGTERM
220 * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown"
221 * to be run after the active task is complete. As a result, SIGTERM
222 * causes all active tasks to be scheduled with reason
223 * "GNUNET_SCHEDULER_REASON_SHUTDOWN". (However, tasks added
224 * afterwards will execute normally!). Note that any particular
225 * signal will only shut down one scheduler; applications should
226 * always only create a single scheduler.
228 * @param task task to run first (and immediately)
229 * @param task_cls closure of task
232 GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls);
236 * Request the shutdown of a scheduler. Marks all currently
237 * pending tasks as ready because of shutdown. This will
238 * cause all tasks to run (as soon as possible, respecting
239 * priorities and prerequisite tasks). Note that tasks
240 * scheduled AFTER this call may still be delayed arbitrarily.
243 GNUNET_SCHEDULER_shutdown (void);
247 * Get information about the current load of this scheduler. Use this
248 * function to determine if an elective task should be added or simply
249 * dropped (if the decision should be made based on the number of
250 * tasks ready to run).
252 * * @param p priority-level to query, use KEEP to query the level
253 * of the current task, use COUNT to get the sum over
254 * all priority levels
255 * @return number of tasks pending right now
258 GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p);
262 * Obtain the reason code for why the current task was
263 * started. Will return the same value as
264 * the GNUNET_SCHEDULER_TaskContext's reason field.
266 * * @return reason(s) why the current task is run
268 enum GNUNET_SCHEDULER_Reason
269 GNUNET_SCHEDULER_get_reason (void);
273 * Cancel the task with the specified identifier.
274 * The task must not yet have run.
276 * * @param task id of the task to cancel
277 * @return the closure of the callback of the cancelled task
280 GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task);
284 * Continue the current execution with the given function. This is
285 * similar to the other "add" functions except that there is no delay
286 * and the reason code can be specified.
288 * * @param task main function of the task
289 * @param task_cls closure of task
290 * @param reason reason for task invocation
293 GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls,
294 enum GNUNET_SCHEDULER_Reason reason);
298 * Continue the current execution with the given function. This is
299 * similar to the other "add" functions except that there is no delay
300 * and the reason code can be specified.
302 * @param task main function of the task
303 * @param task_cls closure for 'main'
304 * @param reason reason for task invocation
305 * @param priority priority to use for the task
308 GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, void *task_cls,
309 enum GNUNET_SCHEDULER_Reason reason,
310 enum GNUNET_SCHEDULER_Priority priority);
314 * Schedule a new task to be run with a specified priority.
316 * * @param prio how important is the new task?
317 * @param task main function of the task
318 * @param task_cls closure of task
319 * @return unique task identifier for the job
320 * only valid until "task" is started!
322 GNUNET_SCHEDULER_TaskIdentifier
323 GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio,
324 GNUNET_SCHEDULER_Task task, void *task_cls);
328 * Schedule a new task to be run as soon as possible. The task
329 * will be run with the DEFAULT priority.
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!
336 GNUNET_SCHEDULER_TaskIdentifier
337 GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls);
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.
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!
354 GNUNET_SCHEDULER_TaskIdentifier
355 GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
356 GNUNET_SCHEDULER_Task task,
361 * Schedule a new task to be run with a specified delay. The task
362 * will be scheduled for execution once the delay has expired. It
363 * will be run with the DEFAULT priority.
365 * * @param delay when should this operation time out? Use
366 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
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!
372 GNUNET_SCHEDULER_TaskIdentifier
373 GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
374 GNUNET_SCHEDULER_Task task, void *task_cls);
378 * Schedule a new task to be run with a specified delay. The task
379 * will be scheduled for execution once the delay has expired.
381 * @param delay when should this operation time out? Use
382 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
383 * @param priority priority to use for the task
384 * @param task main function of the task
385 * @param task_cls closure of task
386 * @return unique task identifier for the job
387 * only valid until "task" is started!
389 GNUNET_SCHEDULER_TaskIdentifier
390 GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
391 enum GNUNET_SCHEDULER_Priority priority,
392 GNUNET_SCHEDULER_Task task, void *task_cls);
396 * Schedule a new task to be run with a specified delay or when the
397 * specified file descriptor is ready for reading. The delay can be
398 * used as a timeout on the socket being ready. The task will be
399 * scheduled for execution once either the delay has expired or the
400 * socket operation is ready. It will be run with the DEFAULT priority.
402 * * @param delay when should this operation time out? Use
403 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
404 * @param rfd read file-descriptor
405 * @param task main function of the task
406 * @param task_cls closure of task
407 * @return unique task identifier for the job
408 * only valid until "task" is started!
410 GNUNET_SCHEDULER_TaskIdentifier
411 GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
412 struct GNUNET_NETWORK_Handle *rfd,
413 GNUNET_SCHEDULER_Task task, void *task_cls);
417 * Schedule a new task to be run with a specified priority and to be
418 * run after the specified delay or when the specified file descriptor
419 * is ready for reading. The delay can be used as a timeout on the
420 * socket being ready. The task will be scheduled for execution once
421 * either the delay has expired or the socket operation is ready. It
422 * will be run with the DEFAULT priority.
424 * @param delay when should this operation time out? Use
425 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
426 * @param priority priority to use for the task
427 * @param rfd read file-descriptor
428 * @param task main function of the task
429 * @param task_cls closure of task
430 * @return unique task identifier for the job
431 * only valid until "task" is started!
433 GNUNET_SCHEDULER_TaskIdentifier
434 GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
435 enum GNUNET_SCHEDULER_Priority priority,
436 struct GNUNET_NETWORK_Handle *rfd,
437 GNUNET_SCHEDULER_Task task, void *task_cls);
441 * Schedule a new task to be run with a specified delay or when the
442 * specified file descriptor is ready for writing. The delay can be
443 * used as a timeout on the socket being ready. The task will be
444 * scheduled for execution once either the delay has expired or the
445 * socket operation is ready. It will be run with the DEFAULT priority.
447 * * @param delay when should this operation time out? Use
448 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
449 * @param wfd write file-descriptor
450 * @param task main function of the task
451 * @param task_cls closure of task
452 * @return unique task identifier for the job
453 * only valid until "task" is started!
455 GNUNET_SCHEDULER_TaskIdentifier
456 GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
457 struct GNUNET_NETWORK_Handle *wfd,
458 GNUNET_SCHEDULER_Task task, void *task_cls);
462 * Schedule a new task to be run with a specified delay or when the
463 * specified file descriptor is ready for reading. The delay can be
464 * used as a timeout on the socket being ready. The task will be
465 * scheduled for execution once either the delay has expired or the
466 * socket operation is ready. It will be run with the DEFAULT priority.
468 * * @param delay when should this operation time out? Use
469 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
470 * @param rfd read file-descriptor
471 * @param task main function of the task
472 * @param task_cls closure of task
473 * @return unique task identifier for the job
474 * only valid until "task" is started!
476 GNUNET_SCHEDULER_TaskIdentifier
477 GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
478 const struct GNUNET_DISK_FileHandle *rfd,
479 GNUNET_SCHEDULER_Task task, void *task_cls);
483 * Schedule a new task to be run with a specified delay or when the
484 * specified file descriptor is ready for writing. The delay can be
485 * used as a timeout on the socket being ready. The task will be
486 * scheduled for execution once either the delay has expired or the
487 * socket operation is ready. It will be run with the DEFAULT priority.
489 * * @param delay when should this operation time out? Use
490 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
491 * @param wfd write file-descriptor
492 * @param task main function of the task
493 * @param task_cls closure of task
494 * @return unique task identifier for the job
495 * only valid until "task" is started!
497 GNUNET_SCHEDULER_TaskIdentifier
498 GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
499 const struct GNUNET_DISK_FileHandle *wfd,
500 GNUNET_SCHEDULER_Task task, void *task_cls);
504 * Schedule a new task to be run with a specified delay or when any of
505 * the specified file descriptor sets is ready. The delay can be used
506 * as a timeout on the socket(s) being ready. The task will be
507 * scheduled for execution once either the delay has expired or any of
508 * the socket operations is ready. This is the most general
509 * function of the "add" family. Note that the "prerequisite_task"
510 * must be satisfied in addition to any of the other conditions. In
511 * other words, the task will be started when
517 * || shutdown-active)
520 * @param prio how important is this task?
521 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever",
522 * which means that the task will only be run after we receive SIGTERM
523 * @param rs set of file descriptors we want to read (can be NULL)
524 * @param ws set of file descriptors we want to write (can be NULL)
525 * @param task main function of the task
526 * @param task_cls closure of task
527 * @return unique task identifier for the job
528 * only valid until "task" is started!
530 GNUNET_SCHEDULER_TaskIdentifier
531 GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
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);
538 * Sets the select function to use in the scheduler (scheduler_select).
540 * @param new_select new select function to use (NULL to reset to default)
541 * @param new_select_cls closure for 'new_select'
544 GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select,
545 void *new_select_cls);
548 #if 0 /* keep Emacsens' auto-indent happy */