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
35 #if 0 /* keep Emacsens' auto-indent happy */
41 * Opaque reference to a task.
43 typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier;
47 * Constant used to indicate that the scheduled
48 * task has no others as prerequisites.
50 #define GNUNET_SCHEDULER_NO_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0)
53 * Reasons why the schedule may have triggered
56 enum GNUNET_SCHEDULER_Reason
59 * This is the very first task run during startup.
61 GNUNET_SCHEDULER_REASON_STARTUP = 0,
64 * We are shutting down and are running all shutdown-related tasks
65 * (regardless of timeout, etc.).
67 GNUNET_SCHEDULER_REASON_SHUTDOWN = 1,
70 * The specified timeout has expired.
71 * (also set if the delay given was 0).
73 GNUNET_SCHEDULER_REASON_TIMEOUT = 2,
76 * The reading socket is ready.
78 GNUNET_SCHEDULER_REASON_READ_READY = 4,
81 * The writing socket is ready.
83 GNUNET_SCHEDULER_REASON_WRITE_READY = 8,
86 * The prerequisite task is done.
88 GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16
93 * Valid task priorities. Use these, do not
94 * pass random integers!
96 enum GNUNET_SCHEDULER_Priority
99 * Run with the same priority as the current job.
101 GNUNET_SCHEDULER_PRIORITY_KEEP = 0,
104 * Run when otherwise idle.
106 GNUNET_SCHEDULER_PRIORITY_IDLE = 1,
109 * Run as background job (higher than idle,
110 * lower than default).
112 GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2,
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.
120 GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3,
123 * Run with high priority (important requests).
124 * Higher than DEFAULT.
126 GNUNET_SCHEDULER_PRIORITY_HIGH = 4,
129 * Run with priority for interactive tasks.
130 * Higher than "HIGH".
132 GNUNET_SCHEDULER_PRIORITY_UI = 5,
135 * Run with priority for urgent tasks. Use
136 * for things like aborts and shutdowns that
137 * need to preempt "UI"-level tasks.
140 GNUNET_SCHEDULER_PRIORITY_URGENT = 6,
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).
150 GNUNET_SCHEDULER_PRIORITY_SHUTDOWN = 7,
153 * Number of priorities (must be the last priority).
154 * This priority must not be used by clients.
156 GNUNET_SCHEDULER_PRIORITY_COUNT = 8
159 #include "gnunet_time_lib.h"
160 #include "gnunet_network_lib.h"
164 * Context information passed to each scheduler task.
166 struct GNUNET_SCHEDULER_TaskContext
169 * Reason why the task is run now
171 enum GNUNET_SCHEDULER_Reason reason;
174 * Set of file descriptors ready for reading;
175 * note that additional bits may be set
176 * that were not in the original request
178 const struct GNUNET_NETWORK_FDSet *read_ready;
181 * Set of file descriptors ready for writing;
182 * note that additional bits may be set
183 * that were not in the original request.
185 const struct GNUNET_NETWORK_FDSet *write_ready;
191 * Signature of the main function of a task.
194 * @param tc context information (why was this task triggered now)
196 typedef void (*GNUNET_SCHEDULER_Task) (void *cls,
197 const struct GNUNET_SCHEDULER_TaskContext
202 * Signature of the select function used by the scheduler.
203 * #GNUNET_NETWORK_socket_select matches it.
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
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);
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.
230 * @param task task to run first (and immediately)
231 * @param task_cls closure of task
234 GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls);
238 * Request the shutdown of a 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.
245 GNUNET_SCHEDULER_shutdown (void);
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).
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
260 GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p);
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.
268 * @return reason(s) why the current task is run
270 enum GNUNET_SCHEDULER_Reason
271 GNUNET_SCHEDULER_get_reason (void);
275 * Cancel the task with the specified identifier.
276 * The task must not yet have run.
278 * @param task id of the task to cancel
279 * @return the closure of the callback of the cancelled task
282 GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task);
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.
290 * @param task main function of the task
291 * @param task_cls closure of task
292 * @param reason reason for task invocation
295 GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls,
296 enum GNUNET_SCHEDULER_Reason reason);
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.
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
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);
316 * Schedule a new task to be run with a specified priority.
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!
324 GNUNET_SCHEDULER_TaskIdentifier
325 GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio,
326 GNUNET_SCHEDULER_Task task, void *task_cls);
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.
337 * The task will be run with the DEFAULT priority.
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!
344 GNUNET_SCHEDULER_TaskIdentifier
345 GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls);
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.
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!
362 GNUNET_SCHEDULER_TaskIdentifier
363 GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
364 GNUNET_SCHEDULER_Task task,
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.
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!
380 GNUNET_SCHEDULER_TaskIdentifier
381 GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
382 GNUNET_SCHEDULER_Task task, void *task_cls);
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.
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!
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);
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.
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!
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);
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.
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!
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);
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.
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!
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);
470 * Schedule a new task to be run with a specified delay or when the
471 * specified file descriptor is ready for reading. 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. It will be run with the DEFAULT priority.
476 * * @param delay when should this operation time out? Use
477 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
478 * @param rfd read file-descriptor
479 * @param task main function of the task
480 * @param task_cls closure of @a task
481 * @return unique task identifier for the job
482 * only valid until "task" is started!
484 GNUNET_SCHEDULER_TaskIdentifier
485 GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
486 const struct GNUNET_DISK_FileHandle *rfd,
487 GNUNET_SCHEDULER_Task task, void *task_cls);
491 * Schedule a new task to be run with a specified delay or when the
492 * specified file descriptor is ready for writing. The delay can be
493 * used as a timeout on the socket being ready. The task will be
494 * scheduled for execution once either the delay has expired or the
495 * socket operation is ready. It will be run with the DEFAULT priority.
497 * * @param delay when should this operation time out? Use
498 * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
499 * @param wfd write file-descriptor
500 * @param task main function of the task
501 * @param task_cls closure of @a task
502 * @return unique task identifier for the job
503 * only valid until @a task is started!
505 GNUNET_SCHEDULER_TaskIdentifier
506 GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
507 const struct GNUNET_DISK_FileHandle *wfd,
508 GNUNET_SCHEDULER_Task task, void *task_cls);
512 * Schedule a new task to be run with a specified delay or when any of
513 * the specified file descriptor sets is ready. The delay can be used
514 * as a timeout on the socket(s) being ready. The task will be
515 * scheduled for execution once either the delay has expired or any of
516 * the socket operations is ready. This is the most general
517 * function of the "add" family. Note that the "prerequisite_task"
518 * must be satisfied in addition to any of the other conditions. In
519 * other words, the task will be started when
525 * || shutdown-active)
528 * @param prio how important is this task?
529 * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever",
530 * which means that the task will only be run after we receive SIGTERM
531 * @param rs set of file descriptors we want to read (can be NULL)
532 * @param ws set of file descriptors we want to write (can be NULL)
533 * @param task main function of the task
534 * @param task_cls closure of @a task
535 * @return unique task identifier for the job
536 * only valid until "task" is started!
538 GNUNET_SCHEDULER_TaskIdentifier
539 GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
540 struct GNUNET_TIME_Relative delay,
541 const struct GNUNET_NETWORK_FDSet *rs,
542 const struct GNUNET_NETWORK_FDSet *ws,
543 GNUNET_SCHEDULER_Task task, void *task_cls);
546 * Sets the select function to use in the scheduler (scheduler_select).
548 * @param new_select new select function to use (NULL to reset to default)
549 * @param new_select_cls closure for 'new_select'
552 GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select,
553 void *new_select_cls);
556 /** @} */ /* end of group scheduler */
558 #if 0 /* keep Emacsens' auto-indent happy */