2 This file is part of GNUnet
3 (C) 2009 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 */
40 * Opaque handle for the scheduling service.
42 struct GNUNET_SCHEDULER_Handle;
45 * Opaque reference to a task.
47 typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier;
51 * Constant used to indicate that the scheduled
52 * task has no others as prerequisites.
54 #define GNUNET_SCHEDULER_NO_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0)
57 * Reasons why the schedule may have triggered
60 enum GNUNET_SCHEDULER_Reason
63 * This is the very first task run during startup.
65 GNUNET_SCHEDULER_REASON_STARTUP = 0,
68 * We are shutting down and are running all shutdown-related tasks
69 * (regardless of timeout, etc.).
71 GNUNET_SCHEDULER_REASON_SHUTDOWN = 1,
74 * The specified timeout has expired.
75 * (also set if the delay given was 0).
77 GNUNET_SCHEDULER_REASON_TIMEOUT = 2,
80 * The reading socket is ready.
82 GNUNET_SCHEDULER_REASON_READ_READY = 4,
85 * The writing socket is ready.
87 GNUNET_SCHEDULER_REASON_WRITE_READY = 8,
90 * The prerequisite task is done.
92 GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16
97 * Valid task priorities. Use these, do not
98 * pass random integers!
100 enum GNUNET_SCHEDULER_Priority
103 * Run with the same priority as the current job.
105 GNUNET_SCHEDULER_PRIORITY_KEEP = 0,
108 * Run when otherwise idle.
110 GNUNET_SCHEDULER_PRIORITY_IDLE = 1,
113 * Run as background job (higher than idle,
114 * lower than default).
116 GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2,
119 * Run with the default priority (normal
120 * P2P operations). Higher than BACKGROUND.
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
172 * Scheduler running the task
174 struct GNUNET_SCHEDULER_Handle *sched;
177 * Reason why the task is run now
179 enum GNUNET_SCHEDULER_Reason reason;
182 * Set of file descriptors ready for reading;
183 * note that additional bits may be set
184 * that were not in the original request
186 const struct GNUNET_NETWORK_FDSet *read_ready;
189 * Set of file descriptors ready for writing;
190 * note that additional bits may be set
191 * that were not in the original request.
193 const struct GNUNET_NETWORK_FDSet *write_ready;
199 * Signature of the main function of a task.
202 * @param tc context information (why was this task triggered now)
204 typedef void (*GNUNET_SCHEDULER_Task) (void *cls,
206 GNUNET_SCHEDULER_TaskContext * tc);
210 * Initialize and run scheduler. This function will return when all
211 * tasks have completed. On systems with signals, receiving a SIGTERM
212 * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown"
213 * to be run after the active task is complete. As a result, SIGTERM
214 * causes all active tasks to be scheduled with reason
215 * "GNUNET_SCHEDULER_REASON_SHUTDOWN". (However, tasks added
216 * afterwards will execute normally!). Note that any particular
217 * signal will only shut down one scheduler; applications should
218 * always only create a single scheduler.
220 * @param task task to run first (and immediately)
221 * @param task_cls closure of task
223 void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls);
227 * Request the shutdown of a scheduler. Marks all currently
228 * pending tasks as ready because of shutdown. This will
229 * cause all tasks to run (as soon as possible, respecting
230 * priorities and prerequisite tasks). Note that tasks
231 * scheduled AFTER this call may still be delayed arbitrarily.
233 * @param sched the scheduler
235 void GNUNET_SCHEDULER_shutdown (struct GNUNET_SCHEDULER_Handle *sched);
239 * Get information about the current load of this scheduler. Use this
240 * function to determine if an elective task should be added or simply
241 * dropped (if the decision should be made based on the number of
242 * tasks ready to run).
244 * @param sched scheduler to query
245 * @param p priority-level to query, use KEEP to query the level
246 * of the current task, use COUNT to get the sum over
247 * all priority levels
248 * @return number of tasks pending right now
250 unsigned int GNUNET_SCHEDULER_get_load (struct GNUNET_SCHEDULER_Handle *sched,
251 enum GNUNET_SCHEDULER_Priority p);
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.
259 * @param sched scheduler to query
260 * @return reason(s) why the current task is run
262 enum GNUNET_SCHEDULER_Reason
263 GNUNET_SCHEDULER_get_reason (struct GNUNET_SCHEDULER_Handle *sched);
267 * Cancel the task with the specified identifier.
268 * The task must not yet have run.
270 * @param sched scheduler to use
271 * @param task id of the task to cancel
272 * @return the closure of the callback of the cancelled task
274 void *GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Handle *sched,
275 GNUNET_SCHEDULER_TaskIdentifier task);
279 * Continue the current execution with the given function. This is
280 * similar to the other "add" functions except that there is no delay
281 * and the reason code can be specified.
283 * @param sched scheduler to use
284 * @param task main function of the task
285 * @param task_cls closure of task
286 * @param reason reason for task invocation
289 GNUNET_SCHEDULER_add_continuation (struct GNUNET_SCHEDULER_Handle *sched,
290 GNUNET_SCHEDULER_Task task,
292 enum GNUNET_SCHEDULER_Reason reason);
296 * Schedule a new task to be run after the specified prerequisite task
297 * has completed. It will be run with the priority of the calling
300 * @param sched scheduler to use
301 * @param prerequisite_task run this task after the task with the given
302 * task identifier completes (and any of our other
303 * conditions, such as delay, read or write-readiness
304 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
305 * on completion of other tasks (this will cause the task to run as
307 * @param task main function of the task
308 * @param task_cls closure of task
309 * @return unique task identifier for the job
310 * only valid until "task" is started!
312 GNUNET_SCHEDULER_TaskIdentifier
313 GNUNET_SCHEDULER_add_after (struct GNUNET_SCHEDULER_Handle *sched,
314 GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
315 GNUNET_SCHEDULER_Task task,
320 * Schedule a new task to be run with a specified priority.
322 * @param sched scheduler to use
323 * @param prio how important is the new task?
324 * @param task main function of the task
325 * @param task_cls closure of task
326 * @return unique task identifier for the job
327 * only valid until "task" is started!
329 GNUNET_SCHEDULER_TaskIdentifier
330 GNUNET_SCHEDULER_add_with_priority (struct GNUNET_SCHEDULER_Handle *sched,
331 enum GNUNET_SCHEDULER_Priority prio,
332 GNUNET_SCHEDULER_Task task,
337 * Schedule a new task to be run as soon as possible. The task
338 * will be run with the priority of the calling task.
340 * @param sched scheduler to use
341 * @param task main function of the task
342 * @param task_cls closure of task
343 * @return unique task identifier for the job
344 * only valid until "task" is started!
346 GNUNET_SCHEDULER_TaskIdentifier
347 GNUNET_SCHEDULER_add_now (struct GNUNET_SCHEDULER_Handle *sched,
348 GNUNET_SCHEDULER_Task task,
353 * Schedule a new task to be run with a specified delay. The task
354 * will be scheduled for execution once the delay has expired. It
355 * will be run with the priority of the calling task.
357 * @param sched scheduler to use
358 * @param delay when should this operation time out? Use
359 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
360 * @param task main function of the task
361 * @param task_cls closure of task
362 * @return unique task identifier for the job
363 * only valid until "task" is started!
365 GNUNET_SCHEDULER_TaskIdentifier
366 GNUNET_SCHEDULER_add_delayed (struct GNUNET_SCHEDULER_Handle *sched,
367 struct GNUNET_TIME_Relative delay,
368 GNUNET_SCHEDULER_Task task,
373 * Schedule a new task to be run with a specified delay or when the
374 * specified file descriptor is ready for reading. The delay can be
375 * used as a timeout on the socket being ready. The task will be
376 * scheduled for execution once either the delay has expired or the
377 * socket operation is ready. It will be run with the priority of
380 * @param sched scheduler to use
381 * @param delay when should this operation time out? Use
382 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
383 * @param rfd read file-descriptor
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_read_net (struct GNUNET_SCHEDULER_Handle *sched,
391 struct GNUNET_TIME_Relative delay,
392 struct GNUNET_NETWORK_Handle *rfd,
393 GNUNET_SCHEDULER_Task task,
398 * Schedule a new task to be run with a specified delay or when the
399 * specified file descriptor is ready for writing. The delay can be
400 * used as a timeout on the socket being ready. The task will be
401 * scheduled for execution once either the delay has expired or the
402 * socket operation is ready. It will be run with the priority of
405 * @param sched scheduler to use
406 * @param delay when should this operation time out? Use
407 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
408 * @param wfd write file-descriptor
409 * @param task main function of the task
410 * @param task_cls closure of task
411 * @return unique task identifier for the job
412 * only valid until "task" is started!
414 GNUNET_SCHEDULER_TaskIdentifier
415 GNUNET_SCHEDULER_add_write_net (struct GNUNET_SCHEDULER_Handle *sched,
416 struct GNUNET_TIME_Relative delay,
417 struct GNUNET_NETWORK_Handle *wfd,
418 GNUNET_SCHEDULER_Task task,
423 * Schedule a new task to be run with a specified delay or when the
424 * specified file descriptor is ready for reading. The delay can be
425 * used as a timeout on the socket being ready. The task will be
426 * scheduled for execution once either the delay has expired or the
427 * socket operation is ready. It will be run with the priority of
430 * @param sched scheduler to use
431 * @param delay when should this operation time out? Use
432 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
433 * @param rfd read file-descriptor
434 * @param task main function of the task
435 * @param task_cls closure of task
436 * @return unique task identifier for the job
437 * only valid until "task" is started!
439 GNUNET_SCHEDULER_TaskIdentifier
440 GNUNET_SCHEDULER_add_read_file (struct GNUNET_SCHEDULER_Handle *sched,
441 struct GNUNET_TIME_Relative delay,
442 const struct GNUNET_DISK_FileHandle *rfd,
443 GNUNET_SCHEDULER_Task task,
448 * Schedule a new task to be run with a specified delay or when the
449 * specified file descriptor is ready for writing. The delay can be
450 * used as a timeout on the socket being ready. The task will be
451 * scheduled for execution once either the delay has expired or the
452 * socket operation is ready. It will be run with the priority of
455 * @param sched scheduler to use
456 * @param delay when should this operation time out? Use
457 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
458 * @param wfd write file-descriptor
459 * @param task main function of the task
460 * @param task_cls closure of task
461 * @return unique task identifier for the job
462 * only valid until "task" is started!
464 GNUNET_SCHEDULER_TaskIdentifier
465 GNUNET_SCHEDULER_add_write_file (struct GNUNET_SCHEDULER_Handle *sched,
466 struct GNUNET_TIME_Relative delay,
467 const struct GNUNET_DISK_FileHandle *wfd,
468 GNUNET_SCHEDULER_Task task,
473 * Schedule a new task to be run with a specified delay or when any of
474 * the specified file descriptor sets is ready. The delay can be used
475 * as a timeout on the socket(s) being ready. The task will be
476 * scheduled for execution once either the delay has expired or any of
477 * the socket operations is ready. This is the most general
478 * function of the "add" family. Note that the "prerequisite_task"
479 * must be satisfied in addition to any of the other conditions. In
480 * other words, the task will be started when
486 * || shutdown-active)
489 * @param sched scheduler to use
490 * @param prio how important is this task?
491 * @param prerequisite_task run this task after the task with the given
492 * task identifier completes (and any of our other
493 * conditions, such as delay, read or write-readiness
494 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
495 * on completion of other tasks.
496 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever",
497 * which means that the task will only be run after we receive SIGTERM
498 * @param rs set of file descriptors we want to read (can be NULL)
499 * @param ws set of file descriptors we want to write (can be NULL)
500 * @param task main function of the task
501 * @param task_cls closure of task
502 * @return unique task identifier for the job
503 * only valid until "task" is started!
505 GNUNET_SCHEDULER_TaskIdentifier
506 GNUNET_SCHEDULER_add_select (struct GNUNET_SCHEDULER_Handle *sched,
507 enum GNUNET_SCHEDULER_Priority prio,
508 GNUNET_SCHEDULER_TaskIdentifier
510 struct GNUNET_TIME_Relative delay,
511 const struct GNUNET_NETWORK_FDSet * rs,
512 const struct GNUNET_NETWORK_FDSet * ws,
513 GNUNET_SCHEDULER_Task task,
516 #if 0 /* keep Emacsens' auto-indent happy */