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). Higher than BACKGROUND.
116 GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3,
119 * Run with high priority (important requests).
120 * Higher than DEFAULT.
122 GNUNET_SCHEDULER_PRIORITY_HIGH = 4,
125 * Run with priority for interactive tasks.
126 * Higher than "HIGH".
128 GNUNET_SCHEDULER_PRIORITY_UI = 5,
131 * Run with priority for urgent tasks. Use
132 * for things like aborts and shutdowns that
133 * need to preempt "UI"-level tasks.
136 GNUNET_SCHEDULER_PRIORITY_URGENT = 6,
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).
146 GNUNET_SCHEDULER_PRIORITY_SHUTDOWN = 7,
149 * Number of priorities (must be the last priority).
150 * This priority must not be used by clients.
152 GNUNET_SCHEDULER_PRIORITY_COUNT = 8
155 #include "gnunet_time_lib.h"
156 #include "gnunet_network_lib.h"
160 * Context information passed to each scheduler task.
162 struct GNUNET_SCHEDULER_TaskContext
165 * Reason why the task is run now
167 enum GNUNET_SCHEDULER_Reason reason;
170 * Set of file descriptors ready for reading;
171 * note that additional bits may be set
172 * that were not in the original request
174 const struct GNUNET_NETWORK_FDSet *read_ready;
177 * Set of file descriptors ready for writing;
178 * note that additional bits may be set
179 * that were not in the original request.
181 const struct GNUNET_NETWORK_FDSet *write_ready;
187 * Signature of the main function of a task.
190 * @param tc context information (why was this task triggered now)
192 typedef void (*GNUNET_SCHEDULER_Task) (void *cls,
194 GNUNET_SCHEDULER_TaskContext * tc);
198 * Initialize and run scheduler. This function will return when all
199 * tasks have completed. On systems with signals, receiving a SIGTERM
200 * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown"
201 * to be run after the active task is complete. As a result, SIGTERM
202 * causes all active tasks to be scheduled with reason
203 * "GNUNET_SCHEDULER_REASON_SHUTDOWN". (However, tasks added
204 * afterwards will execute normally!). Note that any particular
205 * signal will only shut down one scheduler; applications should
206 * always only create a single scheduler.
208 * @param task task to run first (and immediately)
209 * @param task_cls closure of task
211 void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls);
215 * Request the shutdown of a scheduler. Marks all currently
216 * pending tasks as ready because of shutdown. This will
217 * cause all tasks to run (as soon as possible, respecting
218 * priorities and prerequisite tasks). Note that tasks
219 * scheduled AFTER this call may still be delayed arbitrarily.
221 void GNUNET_SCHEDULER_shutdown ();
225 * Get information about the current load of this scheduler. Use this
226 * function to determine if an elective task should be added or simply
227 * dropped (if the decision should be made based on the number of
228 * tasks ready to run).
230 * * @param p priority-level to query, use KEEP to query the level
231 * of the current task, use COUNT to get the sum over
232 * all priority levels
233 * @return number of tasks pending right now
235 unsigned int GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p);
239 * Obtain the reason code for why the current task was
240 * started. Will return the same value as
241 * the GNUNET_SCHEDULER_TaskContext's reason field.
243 * * @return reason(s) why the current task is run
245 enum GNUNET_SCHEDULER_Reason
246 GNUNET_SCHEDULER_get_reason ();
250 * Cancel the task with the specified identifier.
251 * The task must not yet have run.
253 * * @param task id of the task to cancel
254 * @return the closure of the callback of the cancelled task
256 void *GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task);
260 * Continue the current execution with the given function. This is
261 * similar to the other "add" functions except that there is no delay
262 * and the reason code can be specified.
264 * * @param task main function of the task
265 * @param task_cls closure of task
266 * @param reason reason for task invocation
269 GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task,
271 enum GNUNET_SCHEDULER_Reason reason);
275 * Schedule a new task to be run after the specified prerequisite task
276 * has completed. It will be run with the priority of the calling
279 * * @param prerequisite_task run this task after the task with the given
280 * task identifier completes (and any of our other
281 * conditions, such as delay, read or write-readiness
282 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
283 * on completion of other tasks (this will cause the task to run as
285 * @param task main function of the task
286 * @param task_cls closure of task
287 * @return unique task identifier for the job
288 * only valid until "task" is started!
290 GNUNET_SCHEDULER_TaskIdentifier
291 GNUNET_SCHEDULER_add_after (GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
292 GNUNET_SCHEDULER_Task task,
297 * Schedule a new task to be run with a specified priority.
299 * * @param prio how important is the new task?
300 * @param task main function of the task
301 * @param task_cls closure of task
302 * @return unique task identifier for the job
303 * only valid until "task" is started!
305 GNUNET_SCHEDULER_TaskIdentifier
306 GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio,
307 GNUNET_SCHEDULER_Task task,
312 * Schedule a new task to be run as soon as possible. The task
313 * will be run with the priority of the calling task.
315 * * @param task main function of the task
316 * @param task_cls closure of task
317 * @return unique task identifier for the job
318 * only valid until "task" is started!
320 GNUNET_SCHEDULER_TaskIdentifier
321 GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task,
326 * Schedule a new task to be run as soon as possible with the
327 * (transitive) ignore-shutdown flag either explicitly set or
328 * explicitly enabled. This task (and all tasks created from it,
329 * other than by another call to this function) will either count or
330 * not count for the 'lifeness' of the process. This API is only
331 * useful in a few special cases.
333 * @param lifeness GNUNET_YES if the task counts for lifeness, GNUNET_NO if not.
334 * @param task main function of the task
335 * @param task_cls closure of task
336 * @return unique task identifier for the job
337 * only valid until "task" is started!
339 GNUNET_SCHEDULER_TaskIdentifier
340 GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
341 GNUNET_SCHEDULER_Task task,
346 * Schedule a new task to be run with a specified delay. The task
347 * will be scheduled for execution once the delay has expired. It
348 * will be run with the priority of the calling task.
350 * * @param delay when should this operation time out? Use
351 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
352 * @param task main function of the task
353 * @param task_cls closure of task
354 * @return unique task identifier for the job
355 * only valid until "task" is started!
357 GNUNET_SCHEDULER_TaskIdentifier
358 GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
359 GNUNET_SCHEDULER_Task task,
364 * Schedule a new task to be run with a specified delay or when the
365 * specified file descriptor is ready for reading. The delay can be
366 * used as a timeout on the socket being ready. The task will be
367 * scheduled for execution once either the delay has expired or the
368 * socket operation is ready. It will be run with the priority of
371 * * @param delay when should this operation time out? Use
372 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
373 * @param rfd read file-descriptor
374 * @param task main function of the task
375 * @param task_cls closure of task
376 * @return unique task identifier for the job
377 * only valid until "task" is started!
379 GNUNET_SCHEDULER_TaskIdentifier
380 GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
381 struct GNUNET_NETWORK_Handle *rfd,
382 GNUNET_SCHEDULER_Task task,
387 * Schedule a new task to be run with a specified delay or when the
388 * specified file descriptor is ready for writing. The delay can be
389 * used as a timeout on the socket being ready. The task will be
390 * scheduled for execution once either the delay has expired or the
391 * socket operation is ready. It will be run with the priority of
394 * * @param delay when should this operation time out? Use
395 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
396 * @param wfd write file-descriptor
397 * @param task main function of the task
398 * @param task_cls closure of task
399 * @return unique task identifier for the job
400 * only valid until "task" is started!
402 GNUNET_SCHEDULER_TaskIdentifier
403 GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
404 struct GNUNET_NETWORK_Handle *wfd,
405 GNUNET_SCHEDULER_Task task,
410 * Schedule a new task to be run with a specified delay or when the
411 * specified file descriptor is ready for reading. 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
417 * * @param delay when should this operation time out? Use
418 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
419 * @param rfd read 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!
425 GNUNET_SCHEDULER_TaskIdentifier
426 GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
427 const struct GNUNET_DISK_FileHandle *rfd,
428 GNUNET_SCHEDULER_Task task,
433 * Schedule a new task to be run with a specified delay or when the
434 * specified file descriptor is ready for writing. The delay can be
435 * used as a timeout on the socket being ready. The task will be
436 * scheduled for execution once either the delay has expired or the
437 * socket operation is ready. It will be run with the priority of
440 * * @param delay when should this operation time out? Use
441 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
442 * @param wfd write file-descriptor
443 * @param task main function of the task
444 * @param task_cls closure of task
445 * @return unique task identifier for the job
446 * only valid until "task" is started!
448 GNUNET_SCHEDULER_TaskIdentifier
449 GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
450 const struct GNUNET_DISK_FileHandle *wfd,
451 GNUNET_SCHEDULER_Task task,
456 * Schedule a new task to be run with a specified delay or when any of
457 * the specified file descriptor sets is ready. The delay can be used
458 * as a timeout on the socket(s) being ready. The task will be
459 * scheduled for execution once either the delay has expired or any of
460 * the socket operations is ready. This is the most general
461 * function of the "add" family. Note that the "prerequisite_task"
462 * must be satisfied in addition to any of the other conditions. In
463 * other words, the task will be started when
469 * || shutdown-active)
472 * * @param prio how important is this task?
473 * @param prerequisite_task run this task after the task with the given
474 * task identifier completes (and any of our other
475 * conditions, such as delay, read or write-readiness
476 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
477 * on completion of other tasks.
478 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever",
479 * which means that the task will only be run after we receive SIGTERM
480 * @param rs set of file descriptors we want to read (can be NULL)
481 * @param ws set of file descriptors we want to write (can be NULL)
482 * @param task main function of the task
483 * @param task_cls closure of task
484 * @return unique task identifier for the job
485 * only valid until "task" is started!
487 GNUNET_SCHEDULER_TaskIdentifier
488 GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
489 GNUNET_SCHEDULER_TaskIdentifier
491 struct GNUNET_TIME_Relative delay,
492 const struct GNUNET_NETWORK_FDSet * rs,
493 const struct GNUNET_NETWORK_FDSet * ws,
494 GNUNET_SCHEDULER_Task task,
497 #if 0 /* keep Emacsens' auto-indent happy */