gnunet_scheduler_lib.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2009-2015 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. /**
  18. * @author Christian Grothoff
  19. *
  20. * @file
  21. * API to schedule computations using continuation passing style
  22. *
  23. * @defgroup scheduler Scheduler library
  24. * Event loop (scheduler)
  25. *
  26. * Schedule computations using continuation passing style.
  27. *
  28. * @{
  29. */
  30. #ifndef GNUNET_SCHEDULER_LIB_H
  31. #define GNUNET_SCHEDULER_LIB_H
  32. #ifdef __cplusplus
  33. extern "C"
  34. {
  35. #if 0 /* keep Emacsens' auto-indent happy */
  36. }
  37. #endif
  38. #endif
  39. /**
  40. * Opaque reference to a task.
  41. */
  42. struct GNUNET_SCHEDULER_Task;
  43. /**
  44. * Reasons why the schedule may have triggered
  45. * the task now.
  46. */
  47. enum GNUNET_SCHEDULER_Reason
  48. {
  49. /**
  50. * This task is not ready.
  51. */
  52. GNUNET_SCHEDULER_REASON_NONE = 0,
  53. /**
  54. * This is the very first task run during startup.
  55. */
  56. GNUNET_SCHEDULER_REASON_STARTUP = 1,
  57. /**
  58. * We are shutting down and are running all shutdown-related tasks
  59. * (regardless of timeout, etc.).
  60. */
  61. GNUNET_SCHEDULER_REASON_SHUTDOWN = 2,
  62. /**
  63. * The specified timeout has expired.
  64. * (also set if the delay given was 0).
  65. */
  66. GNUNET_SCHEDULER_REASON_TIMEOUT = 4,
  67. /**
  68. * The reading socket is ready.
  69. */
  70. GNUNET_SCHEDULER_REASON_READ_READY = 8,
  71. /**
  72. * The writing socket is ready.
  73. */
  74. GNUNET_SCHEDULER_REASON_WRITE_READY = 16,
  75. /**
  76. * The prerequisite task is done.
  77. */
  78. GNUNET_SCHEDULER_REASON_PREREQ_DONE = 32
  79. };
  80. #include "gnunet_time_lib.h"
  81. #include "gnunet_network_lib.h"
  82. /**
  83. * Context information passed to each scheduler task.
  84. */
  85. struct GNUNET_SCHEDULER_TaskContext
  86. {
  87. /**
  88. * Reason why the task is run now
  89. */
  90. enum GNUNET_SCHEDULER_Reason reason;
  91. /**
  92. * Set of file descriptors ready for reading;
  93. * note that additional bits may be set
  94. * that were not in the original request
  95. */
  96. const struct GNUNET_NETWORK_FDSet *read_ready;
  97. /**
  98. * Set of file descriptors ready for writing;
  99. * note that additional bits may be set
  100. * that were not in the original request.
  101. */
  102. const struct GNUNET_NETWORK_FDSet *write_ready;
  103. };
  104. /**
  105. * Signature of the main function of a task.
  106. *
  107. * @param cls closure
  108. * @param tc context information (why was this task triggered now)
  109. */
  110. typedef void
  111. (*GNUNET_SCHEDULER_TaskCallback) (void *cls,
  112. const struct GNUNET_SCHEDULER_TaskContext *tc);
  113. /**
  114. * Signature of the select function used by the scheduler.
  115. * #GNUNET_NETWORK_socket_select matches it.
  116. *
  117. * @param cls closure
  118. * @param rfds set of sockets to be checked for readability
  119. * @param wfds set of sockets to be checked for writability
  120. * @param efds set of sockets to be checked for exceptions
  121. * @param timeout relative value when to return
  122. * @return number of selected sockets, #GNUNET_SYSERR on error
  123. */
  124. typedef int
  125. (*GNUNET_SCHEDULER_select) (void *cls,
  126. struct GNUNET_NETWORK_FDSet *rfds,
  127. struct GNUNET_NETWORK_FDSet *wfds,
  128. struct GNUNET_NETWORK_FDSet *efds,
  129. struct GNUNET_TIME_Relative timeout);
  130. /**
  131. * Initialize and run scheduler. This function will return when all
  132. * tasks have completed. On systems with signals, receiving a SIGTERM
  133. * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown
  134. * to be run after the active task is complete. As a result, SIGTERM
  135. * causes all active tasks to be scheduled with reason
  136. * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added
  137. * afterwards will execute normally!). Note that any particular
  138. * signal will only shut down one scheduler; applications should
  139. * always only create a single scheduler.
  140. *
  141. * @param task task to run first (and immediately)
  142. * @param task_cls closure of @a task
  143. */
  144. void
  145. GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task,
  146. void *task_cls);
  147. /**
  148. * Request the shutdown of the scheduler. Marks all currently
  149. * pending tasks as ready because of shutdown. This will
  150. * cause all tasks to run (as soon as possible, respecting
  151. * priorities and prerequisite tasks). Note that tasks
  152. * scheduled AFTER this call may still be delayed arbitrarily.
  153. */
  154. void
  155. GNUNET_SCHEDULER_shutdown (void);
  156. /**
  157. * Get information about the current load of this scheduler. Use this
  158. * function to determine if an elective task should be added or simply
  159. * dropped (if the decision should be made based on the number of
  160. * tasks ready to run).
  161. *
  162. * @param p priority-level to query, use KEEP to query the level
  163. * of the current task, use COUNT to get the sum over
  164. * all priority levels
  165. * @return number of tasks pending right now
  166. */
  167. unsigned int
  168. GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p);
  169. /**
  170. * Obtain the reason code for why the current task was
  171. * started. Will return the same value as
  172. * the GNUNET_SCHEDULER_TaskContext's reason field.
  173. *
  174. * @return reason(s) why the current task is run
  175. */
  176. enum GNUNET_SCHEDULER_Reason
  177. GNUNET_SCHEDULER_get_reason (void);
  178. /**
  179. * Cancel the task with the specified identifier.
  180. * The task must not yet have run.
  181. *
  182. * @param task id of the task to cancel
  183. * @return the closure of the callback of the cancelled task
  184. */
  185. void *
  186. GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task);
  187. /**
  188. * Continue the current execution with the given function. This is
  189. * similar to the other "add" functions except that there is no delay
  190. * and the reason code can be specified.
  191. *
  192. * @param task main function of the task
  193. * @param task_cls closure for @a task
  194. * @param reason reason for task invocation
  195. * @param priority priority to use for the task
  196. */
  197. void
  198. GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback task,
  199. void *task_cls,
  200. enum GNUNET_SCHEDULER_Reason reason,
  201. enum GNUNET_SCHEDULER_Priority priority);
  202. /**
  203. * Schedule a new task to be run with a specified priority.
  204. *
  205. * @param prio how important is the new task?
  206. * @param task main function of the task
  207. * @param task_cls closure of @a task
  208. * @return unique task identifier for the job
  209. * only valid until @a task is started!
  210. */
  211. struct GNUNET_SCHEDULER_Task *
  212. GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio,
  213. GNUNET_SCHEDULER_TaskCallback task,
  214. void *task_cls);
  215. /**
  216. * Schedule a new task to be run as soon as possible. Note that this
  217. * does not guarantee that this will be the next task that is being
  218. * run, as other tasks with higher priority (or that are already ready
  219. * to run) might get to run first. Just as with delays, clients must
  220. * not rely on any particular order of execution between tasks
  221. * scheduled concurrently.
  222. *
  223. * The task will be run with the DEFAULT priority.
  224. *
  225. * @param task main function of the task
  226. * @param task_cls closure of @a task
  227. * @return unique task identifier for the job
  228. * only valid until @a task is started!
  229. */
  230. struct GNUNET_SCHEDULER_Task *
  231. GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task,
  232. void *task_cls);
  233. /**
  234. * Schedule a new task to be run as soon as possible with the
  235. * (transitive) ignore-shutdown flag either explicitly set or
  236. * explicitly enabled. This task (and all tasks created from it,
  237. * other than by another call to this function) will either count or
  238. * not count for the 'lifeness' of the process. This API is only
  239. * useful in a few special cases.
  240. *
  241. * @param lifeness #GNUNET_YES if the task counts for lifeness, #GNUNET_NO if not.
  242. * @param task main function of the task
  243. * @param task_cls closure of @a task
  244. * @return unique task identifier for the job
  245. * only valid until @a task is started!
  246. */
  247. struct GNUNET_SCHEDULER_Task *
  248. GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness,
  249. GNUNET_SCHEDULER_TaskCallback task,
  250. void *task_cls);
  251. /**
  252. * Schedule a new task to be run with a specified delay. The task
  253. * will be scheduled for execution once the delay has expired. It
  254. * will be run with the DEFAULT priority.
  255. *
  256. * * @param delay when should this operation time out? Use
  257. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  258. * @param task main function of the task
  259. * @param task_cls closure of @a task
  260. * @return unique task identifier for the job
  261. * only valid until @a task is started!
  262. */
  263. struct GNUNET_SCHEDULER_Task *
  264. GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay,
  265. GNUNET_SCHEDULER_TaskCallback task,
  266. void *task_cls);
  267. /**
  268. * Schedule a new task to be run with a specified delay. The task
  269. * will be scheduled for execution once the delay has expired.
  270. *
  271. * @param delay when should this operation time out? Use
  272. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  273. * @param priority priority to use for the task
  274. * @param task main function of the task
  275. * @param task_cls closure of @a task
  276. * @return unique task identifier for the job
  277. * only valid until @a task is started!
  278. */
  279. struct GNUNET_SCHEDULER_Task *
  280. GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
  281. enum GNUNET_SCHEDULER_Priority priority,
  282. GNUNET_SCHEDULER_TaskCallback task,
  283. void *task_cls);
  284. /**
  285. * Schedule a new task to be run with a specified delay or when the
  286. * specified file descriptor is ready for reading. The delay can be
  287. * used as a timeout on the socket being ready. The task will be
  288. * scheduled for execution once either the delay has expired or the
  289. * socket operation is ready. It will be run with the DEFAULT priority.
  290. *
  291. * * @param delay when should this operation time out? Use
  292. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  293. * @param rfd read file-descriptor
  294. * @param task main function of the task
  295. * @param task_cls closure of @a task
  296. * @return unique task identifier for the job
  297. * only valid until @a task is started!
  298. */
  299. struct GNUNET_SCHEDULER_Task *
  300. GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
  301. struct GNUNET_NETWORK_Handle *rfd,
  302. GNUNET_SCHEDULER_TaskCallback task,
  303. void *task_cls);
  304. /**
  305. * Schedule a new task to be run with a specified priority and to be
  306. * run after the specified delay or when the specified file descriptor
  307. * is ready for reading. The delay can be used as a timeout on the
  308. * socket being ready. The task will be scheduled for execution once
  309. * either the delay has expired or the socket operation is ready. It
  310. * will be run with the DEFAULT priority.
  311. *
  312. * @param delay when should this operation time out? Use
  313. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  314. * @param priority priority to use for the task
  315. * @param rfd read file-descriptor
  316. * @param task main function of the task
  317. * @param task_cls closure of @a task
  318. * @return unique task identifier for the job
  319. * only valid until @a task is started!
  320. */
  321. struct GNUNET_SCHEDULER_Task *
  322. GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
  323. enum GNUNET_SCHEDULER_Priority priority,
  324. struct GNUNET_NETWORK_Handle *rfd,
  325. GNUNET_SCHEDULER_TaskCallback task,
  326. void *task_cls);
  327. /**
  328. * Schedule a new task to be run with a specified delay or when the
  329. * specified file descriptor is ready for writing. The delay can be
  330. * used as a timeout on the socket being ready. The task will be
  331. * scheduled for execution once either the delay has expired or the
  332. * socket operation is ready. It will be run with the DEFAULT priority.
  333. *
  334. * * @param delay when should this operation time out? Use
  335. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  336. * @param wfd write file-descriptor
  337. * @param task main function of the task
  338. * @param task_cls closure of @a task
  339. * @return unique task identifier for the job
  340. * only valid until @a task is started!
  341. */
  342. struct GNUNET_SCHEDULER_Task *
  343. GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
  344. struct GNUNET_NETWORK_Handle *wfd,
  345. GNUNET_SCHEDULER_TaskCallback task,
  346. void *task_cls);
  347. /**
  348. * Schedule a new task to be run with a specified delay or when the
  349. * specified file descriptor is ready. The delay can be
  350. * used as a timeout on the socket being ready. The task will be
  351. * scheduled for execution once either the delay has expired or the
  352. * socket operation is ready.
  353. *
  354. * @param delay when should this operation time out? Use
  355. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  356. * @param priority priority of the task
  357. * @param fd file-descriptor
  358. * @param on_read whether to poll the file-descriptor for readability
  359. * @param on_write whether to poll the file-descriptor for writability
  360. * @param task main function of the task
  361. * @param task_cls closure of @a task
  362. * @return unique task identifier for the job
  363. * only valid until "task" is started!
  364. */
  365. struct GNUNET_SCHEDULER_Task *
  366. GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay,
  367. enum GNUNET_SCHEDULER_Priority priority,
  368. struct GNUNET_NETWORK_Handle *fd,
  369. int on_read,
  370. int on_write,
  371. GNUNET_SCHEDULER_TaskCallback task,
  372. void *task_cls);
  373. /**
  374. * Schedule a new task to be run with a specified delay or when the
  375. * specified file descriptor is ready for reading. The delay can be
  376. * used as a timeout on the socket being ready. The task will be
  377. * scheduled for execution once either the delay has expired or the
  378. * socket operation is ready. It will be run with the DEFAULT priority.
  379. *
  380. * * @param delay when should this operation time out? Use
  381. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  382. * @param rfd read file-descriptor
  383. * @param task main function of the task
  384. * @param task_cls closure of @a task
  385. * @return unique task identifier for the job
  386. * only valid until "task" is started!
  387. */
  388. struct GNUNET_SCHEDULER_Task *
  389. GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
  390. const struct GNUNET_DISK_FileHandle *rfd,
  391. GNUNET_SCHEDULER_TaskCallback task,
  392. void *task_cls);
  393. /**
  394. * Schedule a new task to be run with a specified delay or when the
  395. * specified file descriptor is ready for writing. The delay can be
  396. * used as a timeout on the socket being ready. The task will be
  397. * scheduled for execution once either the delay has expired or the
  398. * socket operation is ready. It will be run with the DEFAULT priority.
  399. *
  400. * * @param delay when should this operation time out? Use
  401. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  402. * @param wfd write file-descriptor
  403. * @param task main function of the task
  404. * @param task_cls closure of @a task
  405. * @return unique task identifier for the job
  406. * only valid until @a task is started!
  407. */
  408. struct GNUNET_SCHEDULER_Task *
  409. GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
  410. const struct GNUNET_DISK_FileHandle *wfd,
  411. GNUNET_SCHEDULER_TaskCallback task,
  412. void *task_cls);
  413. /**
  414. * Schedule a new task to be run with a specified delay or when the
  415. * specified file descriptor is ready. The delay can be
  416. * used as a timeout on the socket being ready. The task will be
  417. * scheduled for execution once either the delay has expired or the
  418. * socket operation is ready.
  419. *
  420. * @param delay when should this operation time out? Use
  421. * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
  422. * @param priority priority of the task
  423. * @param fd file-descriptor
  424. * @param on_read whether to poll the file-descriptor for readability
  425. * @param on_write whether to poll the file-descriptor for writability
  426. * @param task main function of the task
  427. * @param task_cls closure of @a task
  428. * @return unique task identifier for the job
  429. * only valid until @a task is started!
  430. */
  431. struct GNUNET_SCHEDULER_Task *
  432. GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
  433. enum GNUNET_SCHEDULER_Priority priority,
  434. const struct GNUNET_DISK_FileHandle *fd,
  435. int on_read, int on_write,
  436. GNUNET_SCHEDULER_TaskCallback task,
  437. void *task_cls);
  438. /**
  439. * Schedule a new task to be run with a specified delay or when any of
  440. * the specified file descriptor sets is ready. The delay can be used
  441. * as a timeout on the socket(s) being ready. The task will be
  442. * scheduled for execution once either the delay has expired or any of
  443. * the socket operations is ready. This is the most general
  444. * function of the "add" family. Note that the "prerequisite_task"
  445. * must be satisfied in addition to any of the other conditions. In
  446. * other words, the task will be started when
  447. * <code>
  448. * (prerequisite-run)
  449. * && (delay-ready
  450. * || any-rs-ready
  451. * || any-ws-ready
  452. * || shutdown-active)
  453. * </code>
  454. *
  455. * @param prio how important is this task?
  456. * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever",
  457. * which means that the task will only be run after we receive SIGTERM
  458. * @param rs set of file descriptors we want to read (can be NULL)
  459. * @param ws set of file descriptors we want to write (can be NULL)
  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 "task" is started!
  464. */
  465. struct GNUNET_SCHEDULER_Task *
  466. GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
  467. struct GNUNET_TIME_Relative delay,
  468. const struct GNUNET_NETWORK_FDSet *rs,
  469. const struct GNUNET_NETWORK_FDSet *ws,
  470. GNUNET_SCHEDULER_TaskCallback task,
  471. void *task_cls);
  472. /**
  473. * Sets the select function to use in the scheduler (scheduler_select).
  474. *
  475. * @param new_select new select function to use (NULL to reset to default)
  476. * @param new_select_cls closure for 'new_select'
  477. */
  478. void
  479. GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select,
  480. void *new_select_cls);
  481. #if 0 /* keep Emacsens' auto-indent happy */
  482. {
  483. #endif
  484. #ifdef __cplusplus
  485. }
  486. #endif
  487. #endif
  488. /** @} */ /* end of group scheduler */