summaryrefslogtreecommitdiffstats
path: root/doc/tevent_events.dox
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--doc/tevent_events.dox341
1 files changed, 341 insertions, 0 deletions
diff --git a/doc/tevent_events.dox b/doc/tevent_events.dox
new file mode 100644
index 0000000..94fed9c
--- /dev/null
+++ b/doc/tevent_events.dox
@@ -0,0 +1,341 @@
+/**
+@page tevent_events Chapter 2: Tevent events
+@section pools Tevent events
+
+Ok, after reading previous chapter we can start doing something useful. So, the
+way of creating events is similar for all types - signals, file descriptors,
+time or immediate events. At the beginning it is good to know about some
+typedefs which are set in tevent library and which specify the arguments for
+each callback. These callbacks are:
+
+- tevent_timer_handler_t()
+
+- tevent_immediate_handler_t()
+
+- tevent_signal_handler_t()
+
+- tevent_fd_handler_t()
+
+According their names it is obvious that for creating callback for e.g. time
+event, tevent_timer_handler_t will be used.
+
+The best way how to introduce registering an event and setting up a callback
+would be example, so examples describing all the types of events follow.
+
+@subsection Time Time event
+
+This example shows how to set up an event which will be repeated for a minute
+with interval of 2 seconds (will be triggered 30 times). After exceeding this
+limit, the event loop will finish and all the memory resources will be freed.
+This is just example describing repeated activity, nothing useful is done
+within foo function
+
+@code
+#include <stdio.h>
+#include <unistd.h>
+#include <tevent.h>
+#include <sys/time.h>
+
+struct state {
+ struct timeval endtime;
+ int counter;
+ TALLOC_CTX *ctx;
+};
+
+static void callback(struct tevent_context *ev, struct tevent_timer *tim,
+ struct timeval current_time, void *private_data)
+{
+ struct state *data = talloc_get_type_abort(private_data, struct state);
+ struct tevent_timer *time_event;
+ struct timeval schedule;
+
+ printf("Data value: %d\n", data->counter);
+ data->counter += 1; // increase counter
+
+ // if time has not reached its limit, set another event
+ if (tevent_timeval_compare(&current_time, &(data->endtime)) < 0) {
+ // do something
+ // set repeat with delay 2 seconds
+ schedule = tevent_timeval_current_ofs(2, 0);
+ time_event = tevent_add_timer(ev, data->ctx, schedule, callback, data);
+ if (time_event == NULL) { // error ...
+ fprintf(stderr, "MEMORY PROBLEM\n");
+ return;
+ }
+ } else {
+ // time limit exceeded
+ }
+}
+
+int main(void) {
+ struct tevent_context *event_ctx;
+ TALLOC_CTX *mem_ctx;
+ struct tevent_timer *time_event;
+ struct timeval schedule;
+
+ mem_ctx = talloc_new(NULL); // parent
+ event_ctx = tevent_context_init(mem_ctx);
+
+ struct state *data = talloc(mem_ctx, struct state);
+
+ schedule = tevent_timeval_current_ofs(2, 0); // +2 second time value
+ data->endtime = tevent_timeval_add(&schedule, 60, 0); // one minute time limit
+ data->ctx = mem_ctx;
+ data->counter = 0;
+
+ // add time event
+ time_event = tevent_add_timer(event_ctx, mem_ctx, schedule, callback, data);
+ if (time_event == NULL) {
+ fprintf(stderr, "FAILED\n");
+ return EXIT_FAILURE;
+ }
+
+ tevent_loop_wait(event_ctx);
+ talloc_free(mem_ctx);
+ return EXIT_SUCCESS;
+}
+@endcode
+
+Variable <code>counter</code> is only used for counting the number of triggered
+functions. List of all available functions which tevent offers for working with
+time are listed
+<a href="http://tevent.samba.org/group__tevent__helpers.html">here</a> together
+with their description. More detailed view at these functions is unnecessary
+because their purpose and usage is quite simple and clear.
+
+@subsection Immediate Immediate event
+
+These events are, as their name indicates, activated and performed immediately.
+It means that this kind of events have priority over others (except signal
+events). So if there is a bulk of events registered and after that a
+tevent loop is launched, then all the immediate events will be triggered before
+the other events. Except other immediate events (and signal events) because
+they are also processed sequentially - according the order they were scheduled.
+Signals have the highest priority and therefore they are processed
+preferentially. Therefore the expression immediate may not correspond exactly
+to the dictionary definition of "something without delay" but rather "as soon
+as possible" after all preceding immediate events.
+
+For creating an immediate event there is a small different which lies in the
+fact that the creation of such event is done in 2 steps. One represents the
+creation (memory allocation), the second one represents registering as the
+event within some tevent context.
+
+@code
+struct tevent_immediate *run(TALLOC_CTX* mem_ctx,
+ struct tevent_context event_ctx,
+ void * data)
+{
+ struct tevent_immediate *im;
+
+ im = tevent_create_immediate(mem_ctx);
+ if (im == NULL) {
+ return NULL;
+ }
+ tevent_schedule_immediate(im, event_ctx, foo, data);
+
+ return im;
+}
+@endcode
+
+Example which may be compiled and run representing the creation of immediate event.
+
+@code
+
+#include <stdio.h>
+#include <unistd.h>
+#include <tevent.h>
+
+struct info_struct {
+ int counter;
+};
+
+static void foo(struct tevent_context *ev, struct tevent_immediate *im,
+ void *private_data)
+{
+ struct info_struct *data = talloc_get_type_abort(private_data, struct info_struct);
+ printf("Data value: %d\n", data->counter);
+}
+
+int main (void) {
+ struct tevent_context *event_ctx;
+ TALLOC_CTX *mem_ctx;
+ struct tevent_immediate *im;
+
+ printf("INIT\n");
+
+ mem_ctx = talloc_new(NULL);
+ event_ctx = tevent_context_init(mem_ctx);
+
+ struct info_struct *data = talloc(mem_ctx, struct info_struct);
+
+ // setting up private data
+ data->counter = 1;
+
+ // first immediate event
+ im = tevent_create_immediate(mem_ctx);
+ if (im == NULL) {
+ fprintf(stderr, "FAILED\n");
+ return EXIT_FAILURE;
+ }
+ tevent_schedule_immediate(im, event_ctx, foo, data);
+
+ tevent_loop_wait(event_ctx);
+ talloc_free(mem_ctx);
+
+ return 0;
+}
+@endcode
+
+@subsection Signal Signal event
+
+This is an alternative to standard C library functions signal() or sigaction().
+The main difference that distinguishes these ways of treating signals is their
+setting up of handlers for different time intervals of the running program.
+
+While standard C library methods for dealing with signals offer sufficient
+tools for most cases, they are inadequate for handling signals within the
+tevent loop. It could be necessary to finish certain tevent requests within the
+tevent loop without interruption. If a signal was sent to a program at a moment
+when the tevent loop is in progress, a standard signal handler would not return
+processing to the application at the very same place and it would quit the
+tevent loop for ever. In such cases, tevent signal handlers offer the
+possibility of dealing with these signals by masking them from the rest of
+application and not quitting the loop, so the other events can still be
+processed.
+
+Tevent offers also a control function, which enables us to verify whether it is
+possible to handle signals via tevent, is defined within tevent library and it
+returns a boolean value revealing the result of the verification.
+
+@code
+bool tevent_signal_support (struct tevent_context *ev)
+@endcode
+
+Checking for signal support is not necessary, but if it is not guaranteed, this
+is a good and easy control to prevent unexpected behaviour or failure of the
+program occurring. Such a test of course does not have to be run every single
+time you wish to create a signal handler, but simply at the beginning - during
+the initialization procedures of the program. Afterthat, simply adapt to each
+situation that arises.
+
+@code
+
+#include <stdio.h>
+#include <tevent.h>
+#include <signal.h>
+
+static void handler(struct tevent_context *ev,
+ struct tevent_signal *se,
+ int signum,
+ int count,
+ void *siginfo,
+ void *private_data)
+{
+
+ // Do something useful
+
+ printf("handling signal...\n");
+ exit(EXIT_SUCCESS);
+}
+
+int main (void)
+{
+ struct tevent_context *event_ctx;
+ TALLOC_CTX *mem_ctx;
+ struct tevent_signal *sig;
+
+ mem_ctx = talloc_new(NULL); //parent
+ if (mem_ctx == NULL) {
+ fprintf(stderr, "FAILED\n");
+ return EXIT_FAILURE;
+ }
+
+ event_ctx = tevent_context_init(mem_ctx);
+ if (event_ctx == NULL) {
+ fprintf(stderr, "FAILED\n");
+ return EXIT_FAILURE;
+ }
+
+ if (tevent_signal_support(event_ctx)) {
+ // create signal event
+ sig = tevent_add_signal(event_ctx, mem_ctx, SIGINT, 0, handler, NULL);
+ if (sig == NULL) {
+ fprintf(stderr, "FAILED\n");
+ return EXIT_FAILURE;
+ }
+ tevent_loop_wait(event_ctx);
+ }
+
+ talloc_free(mem_ctx);
+ return EXIT_SUCCESS;
+}
+@endcode
+
+
+@subsection File File descriptor event
+
+Support of events on file descriptors is mainly useful for socket communication
+but it certainly works flawlessly with standard streams (stdin, stdout, stderr)
+ as well. Working asynchronously with file descriptors enables switching
+ within processing I/O operations. This ability may rise with a greater
+ number of I/O operations and such overlapping leads to enhancement of the
+ throughput.
+
+There are several other functions included in tevent API related to handling
+file descriptors (there are too many functions defined within tevent therefore
+just some of them are fully described within this thesis. The
+declaration of the rest can be easily found on the library’s website or
+directly from the source code):
+
+<ul>
+<li>tevent_fd_set_close_fn() - can add another function to be called at the
+ moment when a structure tevent fd is freed.</li>
+<li>tevent_fd_set_auto_close() - calling this function can simplify the
+ maintenance of file descriptors, because it instructs tevent to close the
+ appropriate file descriptor when the tevent fd structure is about to be
+ freed.</li>
+<li>tevent_fd_get_flags() - returns flags which are set on the file descriptor
+ connected with this tevent fd structure.</li>
+<li>tevent_fd_set_flags() - sets specified flags on the event’s file
+ descriptor.</li>
+</ul>
+
+@code
+
+static void close_fd(struct tevent_context *ev, struct tevent_fd *fd_event,
+ int fd, void *private_data)
+{
+ // processing when fd_event is freed
+}
+
+struct static void handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags,
+ void *private_data)
+{
+ // handling event; reading from a file descriptor
+ tevent_fd_set_close_fn (fd_event, close_fd);
+}
+
+int run(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx,
+ int fd, uint16_t flags, char *buffer)
+{
+ struct tevent_fd* fd_event = NULL;
+
+ if (flags & TEVENT_FD_READ) {
+ fd_event = tevent_add_fd(event_ctx,
+ mem_ctx,
+ fd,
+ flags,
+ handler,
+ buffer);
+ }
+ if (fd_event == NULL) {
+ // error handling
+ }
+ return tevent_loop_once();
+}
+@endcode
+
+*/