1tevent_events(3)                    tevent                    tevent_events(3)
2
3
4

NAME

6       tevent_events - Chapter 2: Tevent events
7
8

Tevent events

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