diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-03-27 11:44:46 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-03-28 02:27:25 +0200 |
commit | d486f5da0f495d817a19efd077501c25e4eef6fa (patch) | |
tree | bb785996088c46ed38012b23698d6354f8da7cfe /src/include/gnunet_scheduler_lib.h | |
parent | 802f89d2979d3a92228543d42cee6bb8e3e786d1 (diff) | |
download | gnunet-d486f5da0f495d817a19efd077501c25e4eef6fa.tar.gz gnunet-d486f5da0f495d817a19efd077501c25e4eef6fa.zip |
initial ideas for improving the scheduler API (far from finished)
Diffstat (limited to 'src/include/gnunet_scheduler_lib.h')
-rw-r--r-- | src/include/gnunet_scheduler_lib.h | 246 |
1 files changed, 238 insertions, 8 deletions
diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 2be1858ce..a7385e31c 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h | |||
@@ -97,6 +97,84 @@ enum GNUNET_SCHEDULER_Reason | |||
97 | 97 | ||
98 | 98 | ||
99 | /** | 99 | /** |
100 | * Possible events on FDs, used as a bitmask. | ||
101 | * Modelled after GPollFD. | ||
102 | */ | ||
103 | enum GNUNET_SCHEDULER_EventType | ||
104 | { | ||
105 | |||
106 | /** | ||
107 | * No event (useful for timeout). | ||
108 | */ | ||
109 | GNUNET_SCHEDULER_ET_NONE = 0, | ||
110 | |||
111 | /** | ||
112 | * Data available for reading. | ||
113 | */ | ||
114 | GNUNET_SCHEDULER_ET_IN = 1, | ||
115 | |||
116 | /** | ||
117 | * Buffer available for writing. | ||
118 | */ | ||
119 | GNUNET_SCHEDULER_ET_OUT = 2, | ||
120 | |||
121 | /** | ||
122 | * | ||
123 | */ | ||
124 | GNUNET_SCHEDULER_ET_HUP = 4, | ||
125 | |||
126 | /** | ||
127 | * | ||
128 | */ | ||
129 | GNUNET_SCHEDULER_ET_ERR = 8, | ||
130 | |||
131 | /** | ||
132 | * | ||
133 | */ | ||
134 | GNUNET_SCHEDULER_ET_PRI = 16, | ||
135 | |||
136 | /** | ||
137 | * | ||
138 | */ | ||
139 | GNUNET_SCHEDULER_ET_NVAL = 32 | ||
140 | |||
141 | }; | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Information about an event relating to a file descriptor/socket. | ||
146 | */ | ||
147 | struct GNUNET_SCHEDULER_FdInfo | ||
148 | { | ||
149 | |||
150 | /** | ||
151 | * GNUnet network socket the event is about, matches @a sock, | ||
152 | * NULL if this is about a file handle or if no network | ||
153 | * handle was given to the scheduler originally. | ||
154 | */ | ||
155 | struct GNUNET_NETWORK_Handle *fd; | ||
156 | |||
157 | /** | ||
158 | * GNUnet file handle the event is about, matches @a sock, | ||
159 | * NULL if this is about a network socket or if no network | ||
160 | * handle was given to the scheduler originally. | ||
161 | */ | ||
162 | struct GNUNET_DISK_FileHandle *fh; | ||
163 | |||
164 | /** | ||
165 | * Type of the event that was generated related to @e sock. | ||
166 | */ | ||
167 | enum GNUNET_SCHEDULER_EventType et; | ||
168 | |||
169 | /** | ||
170 | * Underlying OS handle the event was about. | ||
171 | */ | ||
172 | int sock; | ||
173 | |||
174 | }; | ||
175 | |||
176 | |||
177 | /** | ||
100 | * Context information passed to each scheduler task. | 178 | * Context information passed to each scheduler task. |
101 | */ | 179 | */ |
102 | struct GNUNET_SCHEDULER_TaskContext | 180 | struct GNUNET_SCHEDULER_TaskContext |
@@ -107,16 +185,29 @@ struct GNUNET_SCHEDULER_TaskContext | |||
107 | enum GNUNET_SCHEDULER_Reason reason; | 185 | enum GNUNET_SCHEDULER_Reason reason; |
108 | 186 | ||
109 | /** | 187 | /** |
110 | * Set of file descriptors ready for reading; | 188 | * Length of the following array. |
111 | * note that additional bits may be set | 189 | */ |
112 | * that were not in the original request | 190 | unsigned int fds_len; |
191 | |||
192 | /** | ||
193 | * Array of length @e fds_len with information about ready FDs. | ||
194 | * Note that we use the same format regardless of the internal | ||
195 | * event loop that was used. The given array should only contain | ||
196 | * information about file descriptors relevant to the current task. | ||
197 | */ | ||
198 | const struct GNUNET_SCHEDULER_FdInfo *fds; | ||
199 | |||
200 | /** | ||
201 | * Set of file descriptors ready for reading; note that additional | ||
202 | * bits may be set that were not in the original request. | ||
203 | * @deprecated | ||
113 | */ | 204 | */ |
114 | const struct GNUNET_NETWORK_FDSet *read_ready; | 205 | const struct GNUNET_NETWORK_FDSet *read_ready; |
115 | 206 | ||
116 | /** | 207 | /** |
117 | * Set of file descriptors ready for writing; | 208 | * Set of file descriptors ready for writing; note that additional |
118 | * note that additional bits may be set | 209 | * bits may be set that were not in the original request. |
119 | * that were not in the original request. | 210 | * @deprecated |
120 | */ | 211 | */ |
121 | const struct GNUNET_NETWORK_FDSet *write_ready; | 212 | const struct GNUNET_NETWORK_FDSet *write_ready; |
122 | 213 | ||
@@ -124,16 +215,155 @@ struct GNUNET_SCHEDULER_TaskContext | |||
124 | 215 | ||
125 | 216 | ||
126 | /** | 217 | /** |
218 | * Function used by event-loop implementations to signal the scheduler | ||
219 | * that a particular @a task is ready due to an event of type @a et. | ||
220 | * | ||
221 | * This function will then queue the task to notify the application | ||
222 | * that the task is ready (with the respective priority). | ||
223 | * | ||
224 | * @param task the task that is ready | ||
225 | * @param et information about why the task is ready | ||
226 | */ | ||
227 | void | ||
228 | GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | ||
229 | enum GNUNET_SCHEDULER_EventType et); | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Handle to the scheduler's state to be used by the driver. | ||
234 | */ | ||
235 | struct GNUNET_SCHEDULER_Handle; | ||
236 | |||
237 | |||
238 | /** | ||
239 | * Function called by the driver to tell the scheduler to run some of | ||
240 | * the tasks that are ready. This function may return even though | ||
241 | * there are tasks left to run just to give other tasks a chance as | ||
242 | * well. If we return #GNUNET_YES, the driver should call this | ||
243 | * function again as soon as possible, while if we return #GNUNET_NO | ||
244 | * it must block until the operating system has more work as the | ||
245 | * scheduler has no more work to do right now. | ||
246 | * | ||
247 | * @param sh scheduler handle that was given to the `loop` | ||
248 | * @return #GNUNET_OK if there are more tasks that are ready, | ||
249 | * and thus we would like to run more (yield to avoid | ||
250 | * blocking other activities for too long) | ||
251 | * #GNUNET_NO if we are done running tasks (yield to block) | ||
252 | * #GNUNET_SYSERR on error | ||
253 | */ | ||
254 | int | ||
255 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh); | ||
256 | |||
257 | |||
258 | /** | ||
259 | * API a driver has to implement for | ||
260 | * #GNUNET_SCHEDULER_run_with_driver(). | ||
261 | */ | ||
262 | struct GNUNET_SCHEDULER_Driver | ||
263 | { | ||
264 | |||
265 | /** | ||
266 | * Closure to pass to the functions in this struct. | ||
267 | */ | ||
268 | void *cls; | ||
269 | |||
270 | /** | ||
271 | * Add a @a task to be run if the conditions given | ||
272 | * in @a fdi are satisfied. | ||
273 | * | ||
274 | * @param cls closure | ||
275 | * @param task task to add | ||
276 | * @param fdi conditions to watch for | ||
277 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
278 | * (i.e. @a fdi too high or invalid) | ||
279 | */ | ||
280 | int | ||
281 | (*add)(void *cls, | ||
282 | struct GNUNET_SCHEDULER_Task *task, | ||
283 | struct GNUNET_SCHEDULER_FdInfo *fdi); | ||
284 | |||
285 | /** | ||
286 | * Delete a @a task from the set of tasks to be run. | ||
287 | * | ||
288 | * @param cls closure | ||
289 | * @param task task to delete | ||
290 | * @param fdi conditions to watch for (must match @e add call) | ||
291 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
292 | * (i.e. @a task or @a fdi do not match prior @e add call) | ||
293 | */ | ||
294 | int | ||
295 | (*del)(void *cls, | ||
296 | struct GNUNET_SCHEDULER_Task *task, | ||
297 | const struct GNUNET_SCHEDULER_FdInfo *fdi); | ||
298 | |||
299 | /** | ||
300 | * Set time at which we definitively want to get a wakeup call. | ||
301 | * | ||
302 | * @param cls closure | ||
303 | * @param dt time when we want to wake up next | ||
304 | */ | ||
305 | void | ||
306 | (*set_wakeup)(void *cls, | ||
307 | struct GNUNET_TIME_Absolute dt); | ||
308 | |||
309 | /** | ||
310 | * Event loop's "main" function, to be called from | ||
311 | * #GNUNET_SCHEDULER_run_with_driver() to actually | ||
312 | * launch the loop. | ||
313 | * | ||
314 | * @param cls closure | ||
315 | * @param sh scheduler handle to pass to | ||
316 | * #GNUNET_SCHEDULER_run_from_driver() | ||
317 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
318 | */ | ||
319 | int | ||
320 | (*loop)(void *cls, | ||
321 | struct GNUNET_SCHEDULER_Handle *sh); | ||
322 | |||
323 | }; | ||
324 | |||
325 | |||
326 | /** | ||
127 | * Signature of the main function of a task. | 327 | * Signature of the main function of a task. |
128 | * | 328 | * |
129 | * @param cls closure | 329 | * @param cls closure |
130 | * @param tc context information (why was this task triggered now) | ||
131 | */ | 330 | */ |
132 | typedef void | 331 | typedef void |
133 | (*GNUNET_SCHEDULER_TaskCallback) (void *cls); | 332 | (*GNUNET_SCHEDULER_TaskCallback) (void *cls); |
134 | 333 | ||
135 | 334 | ||
136 | /** | 335 | /** |
336 | * Initialize and run scheduler. This function will return when all | ||
337 | * tasks have completed. On systems with signals, receiving a SIGTERM | ||
338 | * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown | ||
339 | * to be run after the active task is complete. As a result, SIGTERM | ||
340 | * causes all shutdown tasks to be scheduled with reason | ||
341 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added | ||
342 | * afterwards will execute normally!). Note that any particular | ||
343 | * signal will only shut down one scheduler; applications should | ||
344 | * always only create a single scheduler. | ||
345 | * | ||
346 | * @param driver drive to use for the event loop | ||
347 | * @param task task to run first (and immediately) | ||
348 | * @param task_cls closure of @a task | ||
349 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
350 | */ | ||
351 | int | ||
352 | GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | ||
353 | GNUNET_SCHEDULER_TaskCallback task, | ||
354 | void *task_cls); | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Obtain the driver for using select() as the event loop. | ||
359 | * | ||
360 | * @return NULL on error | ||
361 | */ | ||
362 | const struct GNUNET_SCHEDULER_Driver * | ||
363 | GNUNET_SCHEDULER_driver_select (void); | ||
364 | |||
365 | |||
366 | /** | ||
137 | * Signature of the select function used by the scheduler. | 367 | * Signature of the select function used by the scheduler. |
138 | * #GNUNET_NETWORK_socket_select matches it. | 368 | * #GNUNET_NETWORK_socket_select matches it. |
139 | * | 369 | * |
@@ -571,7 +801,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
571 | * Sets the select function to use in the scheduler (scheduler_select). | 801 | * Sets the select function to use in the scheduler (scheduler_select). |
572 | * | 802 | * |
573 | * @param new_select new select function to use (NULL to reset to default) | 803 | * @param new_select new select function to use (NULL to reset to default) |
574 | * @param new_select_cls closure for 'new_select' | 804 | * @param new_select_cls closure for @a new_select |
575 | */ | 805 | */ |
576 | void | 806 | void |
577 | GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select, | 807 | GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select, |