Mainloop
========
-Not every program is sequential. You may need an event driven program
-sometime, lets say a railway server. It has a connection to each
-station and train to know, where each one is, some things happen at
-given times, like train is scheduled to leave as station and so on.
+Not every program is strictly sequential. Sometimes, an event-driven
+model is much easier to grasp. A fine example of such a program could
+be a railway server. It has a separate connection to each station
+and also to each train, so that it knows where each of them is (and
+that neither a train nor a station have got missing). So it has to wait
+for events coming from these connections and handle them appropriately.
+It also processes other events that it has itself generated -- for
+example various timers telling that a train is scheduled to depart
+from some station.
-With the mainloop module you can write just the hooks and tell it to
-watch over a set of file descriptors, timers and running processes.
+The mainloop module takes care of the low-level part of event-driven
+programs: it calls the OS to monitor file activity, to interrupt
+the program at the right moment to serve a timer, and so on. The
+programmer only defines hooks that should be called to handle
+the events and calls mainloop functions to schedule them.
// TODO Example?
- <<conventions,Conventions>>
-- <<time,Time manipulation>>
+- <<time,Time and timers>>
- <<file,Activity on file descriptors>>
- <<hooks,Loop hooks>>
- <<process,Child processes>>
* Conventions
* -----------
*
- * The description of structures contain some fields marked as `[*]`.
- * These are the only ones that are user defined. The rest is for
- * internal use and you must initialize it to zeroes.
+ * The descriptions of structures contain some fields marked with `[*]`.
+ * These are the only ones that are intended to be manipulated by the user.
+ * The remaining fields serve for internal use only and you must initialize them
+ * to zeroes.
***/
/***
* Time manipulation
* -----------------
*
- * This part allows you to know the current time and request
+ * This part allows you to get the current time and request
* to have your function called when the time comes.
***/
-extern timestamp_t main_now; /** Current time in milliseconds since UNIX epoch. See @main_get_time(). **/
+extern timestamp_t main_now; /** Current time in milliseconds since the UNIX epoch. See @main_get_time(). **/
extern ucw_time_t main_now_seconds; /** Current time in seconds since the epoch. **/
extern clist main_timer_list, main_file_list, main_hook_list, main_process_list;
/**
* This is a description of a timer.
- * You fill it with a handler function, any user-defined data and
- * add it using @timer_add().
+ * You fill in a handler function, any user-defined data you wish to pass
+ * to the handler, and then you invoke @timer_add().
*
- * The handler() function must add it again or delete it with
- * @timer_del().
+ * The handler() function must either call @timer_del() to delete the timer,
+ * or call @timer_add() with a different expiration time.
**/
struct main_timer {
cnode n;
};
/**
- * Adds a new timer into the mainloop to be watched and called,
- * when it expires. It can be used to modify an already running
- * timer.
+ * Adds a new timer into the mainloop to be watched and called
+ * when it expires. It can also be used to modify an already running
+ * timer. It is permitted (and usual) to call this function from the
+ * timer's handler itself if you want the timer to trigger again.
*
- * The @expire parameter is absolute -- you may use
- * <<var_main_now,`main_now`>>, if you need it relative to now.
+ * The @expire parameter is absolute, just add <<var_main_now,`main_now`>> if you need a relative timer.
**/
void timer_add(struct main_timer *tm, timestamp_t expires);
/**
- * Removes a timer from the watched ones. You need to call this, when
- * the timer expires and you do not want to use it any more. It can be
- * used to remove a still active timer too.
+ * Removes a timer from the active ones. It is permitted (and usual) to call
+ * this function from the timer's handler itself if you want to deactivate
+ * the timer.
**/
void timer_del(struct main_timer *tm);