tevent: Add tevent tutorial files.
[Samba/bjacke.git] / lib / tevent / doc / tevent_events.dox
blob8e350d2b93e086394e2544c522226f477fe46b3e
1 /**
2 @page tevent_events Chapter 2: Tevent events
3 @section pools Tevent events
5 Ok, after reading previous chapter we can start doing something useful. So, the
6 way of creating events is similar for all types - signals, file descriptors,
7 time or immediate events. At the beginning it is good to know about some
8 typedefs which are set in tevent library and which specify the arguments for
9 each callback. These callbacks are:
11 - tevent_timer_handler_t()
13 - tevent_immediate_handler_t()
15 - tevent_signal_handler_t()
17 - tevent_fd_handler_t()
19 According their names it is obvious that for creating callback for e.g. time
20 event, tevent_timer_handler_t will be used.
22 The best way how to introduce registering an event and setting up a callback
23 would be example, so examples describing all the types of events follow.
25 @subsection Time Time event
27 This example shows how to set up an event which will be repeated for a minute
28 with interval of 2 seconds (will be triggered 30 times). After exceeding this
29 limit, the event loop will finish and all the memory resources will be freed.
30 This is just example describing repeated activity, nothing usefull is done
31 within foo function
33 @code
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <tevent.h>
37 #include <sys/time.h>
39 struct state {
40      struct timeval endtime;
41      int counter;
42      TALLOC_CTX *ctx;
45 static void callback(struct tevent_context *ev, struct tevent_timer *tim,
46                      struct timeval current_time, void *private_data)
48     struct state *data = talloc_get_type(private_data, struct state);
49     struct tevent_timer *time_event;
50     struct timeval schedule;
52     printf("Data value: %d\n", data->counter);
53     data->counter += 1; // increase counter
55     // if time has not reached its limit, set another event
56     if (tevent_timeval_compare(&current_time, &(data->endtime)) < 0) {
57         // do something
58         // set repeat with delay 2 seconds
59         schedule = tevent_timeval_current_ofs(2, 0);
60         time_event = tevent_add_timer(ev, data->ctx, schedule, callback, data);
61         if (time_event == NULL) { // error ...
62             fprintf(stderr, "MEMORY PROBLEM\n");
63             return;
64         }
65     } else {
66         // time limit exceeded
67     }
70 int main(void)  {
71     struct tevent_context *event_ctx;
72     TALLOC_CTX *mem_ctx;
73     struct tevent_timer *time_event;
74     struct timeval schedule;
76     mem_ctx = talloc_new(NULL); // parent
77     event_ctx = tevent_context_init(mem_ctx);
79     struct state *data = talloc(mem_ctx, struct state);
81     schedule = tevent_timeval_current_ofs(2, 0); // +2 second time value
82     data->endtime = tevent_timeval_add(&schedule, 60, 0); // one minute time limit
83     data->ctx = mem_ctx;
84     data->counter = 0;
86     // add time event
87     time_event = tevent_add_timer(event_ctx, mem_ctx, schedule, callback, data);
88     if (time_event == NULL) {
89         fprintf(stderr, "FAILED\n");
90         return EXIT_FAILURE;
91     }
93     tevent_loop_wait(event_ctx);
94     talloc_free(mem_ctx);
95     return EXIT_SUCCESS;
97 @endcode
99 Variable <code>counter</code> is only used for counting the number of triggered
100 functions. List of all available functions which tevent offers for working with
101 time are listed
102 <a href="http://tevent.samba.org/group__tevent__helpers.html">here</a> together
103 with their description. More detailed view at these functions is unnecessary
104 because their purpose and usage is quite simple and clear.
106 @subsection Immediate Immediate event
108 These events are, as their name indicates, activated and performed immediately.
109 It means that this kind of events have priority over others (except signal
110 events). So if there is a bulk of events registered and after that a
111 tevent loop is launched, then all the immediate events will be triggered before
112 the other events. Except other immediate events (and signal events) because
113 they are also processed sequentially - according the order they were scheduled.
114 Signals have the highest priority and therefore they are processed
115 preferentially. Therefore the expression immediate may not correspond exactly
116 to the dictionary definition of "something without delay" but rather "as soon
117 as possible" after all preceding immediate events.
119 For creating an immediate event there is a small different which lies in the
120 fact that the creation of such event is done in 2 steps. One represents the
121 creation (memory allocation), the second one represents registering as the
122 event within some tevent context.
124 @code
125 struct tevent_immediate *run(TALLOC_CTX* mem_ctx,
126                              struct tevent_context event_ctx,
127                              void * data)
129     struct tevent_immediate *im;
131     im = tevent_create_immediate(mem_ctx);
132     if (im == NULL) {
133         return NULL;
134     }
135     tevent_schedule_immediate(im, event_ctx, foo, data);
137     return im;
139 @endcode
141 Example which may be compiled and run representing the creation of immediate event.
143 @code
145 #include <stdio.h>
146 #include <unistd.h>
147 #include <tevent.h>
149 struct info_struct {
150     int counter;
153 static void foo(struct tevent_context *ev, struct tevent_immediate *im,
154                 void *private_data)
156     struct info_struct *data = talloc_get_type(private_data, struct info_struct);
157     printf("Data value: %d\n", data->counter);
160 int main (void) {
161     struct tevent_context *event_ctx;
162     TALLOC_CTX *mem_ctx;
163     struct tevent_immediate *im;
165     printf("INIT\n");
167     mem_ctx = talloc_new(NULL);
168     event_ctx = tevent_context_init(mem_ctx);
170     struct info_struct *data = talloc(mem_ctx, struct info_struct);
172     // setting up private data
173     data->counter = 1;
175     // first immediate event
176     im = tevent_create_immediate(mem_ctx);
177     if (im == NULL) {
178         fprintf(stderr, "FAILED\n");
179         return EXIT_FAILURE;
180     }
181     tevent_schedule_immediate(im, event_ctx, foo, data);
183     tevent_loop_wait(event_ctx);
184     talloc_free(mem_ctx);
186     return 0;
188 @endcode
190 @subsection Signal Signal event
192 This is an alternative to standard C library functions signal() or sigaction().
193 The main difference that distinguishes these ways of treating signals is their
194 setting up of handlers for different time intervals of the running program. 
196 While standard C library methods for dealing with signals offer sufficient
197 tools for most cases, they are inadequate for handling signals within the
198 tevent loop. It could be necessary to finish certain tevent requests within the
199 tevent loop without interruption. If a signal was sent to a program at a moment
200 when the tevent loop is in progress, a standard signal handler would not return
201 processing to the application at the very same place and it would quit the
202 tevent loop for ever. In such cases, tevent signal handlers offer the
203 possibility of dealing with these signals by masking them from the rest of
204 application and not quitting the loop, so the other events can still be
205 processed.
207 Tevent offers also a control function, which enables us to verify whether it is
208 possible to handle signals via tevent, is defined within tevent library and it
209 returns a boolean value revealing the result of the verification.
211 @code
212 bool tevent_signal_support (struct tevent_context *ev)
213 @endcode
215 Checking for signal support is not necessary, but if it is not guaranteed, this
216 is a good and easy control to prevent unexpected behaviour or failure of the
217 program occurring. Such a test of course does not have to be run every single
218 time you wish to create a signal handler, but simply at the beginning - during
219 the initialization procedures of the program. Afterthat, simply adapt to each
220 situation that arises.
222 @code
224 #include <stdio.h>
225 #include <tevent.h>
226 #include <signal.h>
228 static void handler(struct tevent_context *ev,
229                     struct tevent_signal *se,
230                     int signum,
231                     int count,
232                     void *siginfo,
233                     void *private_data)
236     // Do something usefull
238     printf("handling signal...\n");
239     exit(EXIT_SUCCESS);
242 int main (void)
244     struct tevent_context *event_ctx;
245     TALLOC_CTX *mem_ctx;
246     struct tevent_signal *sig;
248     mem_ctx = talloc_new(NULL); //parent
249     if (mem_ctx == NULL) {
250         fprintf(stderr, "FAILED\n");
251         return EXIT_FAILURE;
252     }
254     event_ctx = tevent_context_init(mem_ctx);
255     if (event_ctx == NULL) {
256         fprintf(stderr, "FAILED\n");
257         return EXIT_FAILURE;
258     }
260     if (tevent_signal_support(event_ctx)) {
261         // create signal event
262         sig = tevent_add_signal(event_ctx, mem_ctx, SIGINT, 0, handler, NULL);
263         if (sig == NULL) {
264             fprintf(stderr, "FAILED\n");
265             return EXIT_FAILURE;
266         }
267         tevent_loop_wait(event_ctx);
268     }
270     talloc_free(mem_ctx);
271     return EXIT_SUCCESS;
273 @endcode
276 @subsection File File descriptor event
278 Support of events on file descriptors is mainly useful for socket communication
279 but it certainly works flawlessly with standard streams (stdin, stdout, stderr)
280     as well. Working asynchronously with file descriptors enables switching
281     within processing I/O operations. This ability may rise with a greater
282     number of I/O operations and such overlapping leads to enhancement of the
283     throughput.
285 There are several other functions included in tevent API related to handling
286 file descriptors (there are too many functions defined within tevent therefore
287 just some of them are fully described within this thesis. The
288 declaration of the rest can be easily found on the library’s website or
289 directly from the source code):
291 <ul>
292 <li>tevent_fd_set_close_fn() - can add another function to be called at the
293     moment when a structure tevent fd is freed.</li>
294 <li>tevent_fd_set_auto_close() - calling this function can simplify the
295     maintenance of file descriptors, because it instructs tevent to close the
296     appropriate file descriptor when the tevent fd structure is about to be
297     freed.</li>
298 <li>tevent_fd_get_flags() - returns flags which are set on the file descriptor
299     connected with this tevent fd structure.</li>
300 <li>tevent_fd_set_flags() - sets specified flags on the event’s file
301     descriptor.</li>
302 </ul>
304 @code
306 static void close_fd(struct tevent_context *ev, struct tevent_fd *fd_event,
307                      int fd, void *private_data)
309     // processing when fd_event is freed
312 struct static void handler(struct tevent_context *ev,
313                            struct tevent_fd *fde,
314                            uint16_t flags,
315                            void *private_data)
317     // handling event; reading from a file descriptor
318     tevent_fd_set_close_fn (fd_event, close_fd);
321 int run(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx,
322         int fd, uint16_t flags, char *buffer)
324     struct tevent_fd* fd_event = NULL;
326     if (flags & TEVENT_FD_READ) {
327         fd_event = tevent_add_fd(event_ctx,
328                                  mem_ctx,
329                                  fd,
330                                  flags,
331                                  handler,
332                                  buffer);
333     }
334     if (fd_event == NULL) {
335         // error handling
336     }
337     return tevent_loop_once();
339 @endcode