tevent_data - Man Page

Chapter 3: Accessing data

Accessing data with tevent

A tevent request is (usually) created together with a structure for storing the data necessary for an asynchronous computation. For these private data, tevent library uses void (generic) pointers, therefore any data type can be very simply pointed at. However, this attitude requires clear and guaranteed knowledge of the data type that will be handled, in advance. Private data can be of 2 types: connected with a request itself or given as an individual argument to a callback. It is necessary to differentiate these types, because there is a slightly different method of data access for each. There are two possibilities how to access data that is given as an argument directly to a callback. The difference lies in the pointer that is returned. In one case it is the data type specified in the function’s argument, in another void* is returned.

void tevent_req_callback_data (struct tevent_req *req, #type)
void tevent_req_callback_data_void (struct tevent_req *req)

To obtain data that are strictly bound to a request, this function is the only direct procedure.

void *tevent_req_data (struct tevent_req *req, #type)

Example with both calls which differs between private data within tevent request and data handed over as an argument.

#include <stdio.h>
#include <unistd.h>
#include <tevent.h>

struct foo_state {
    int x;
};

struct testA {
    int y;
};


static void foo_done(struct tevent_req *req) {
    // a->x contains 10 since it came from foo_send
    struct foo_state *a = tevent_req_data(req, struct foo_state);

    // b->y contains 9 since it came from run
    struct testA *b = tevent_req_callback_data(req, struct testA);

    // c->y contains 9 since it came from run we just used a different way
    // of getting it.
    struct testA *c = (struct testA *)tevent_req_callback_data_void(req);

    printf("a->x: %d\n", a->x);
    printf("b->y: %d\n", b->y);
    printf("c->y: %d\n", c->y);
}


struct tevent_req * foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx) {

printf("_send\n");
struct tevent_req *req;
struct foo_state *state;

req = tevent_req_create(event_ctx, &state, struct foo_state);
state->x = 10;

return req;
}

static void run(struct tevent_context *ev, struct tevent_timer *te,
                struct timeval current_time, void *private_data) {
    struct tevent_req *req;
    struct testA *tmp = talloc(ev, struct testA);

    // Note that we did not use the private data passed in

    tmp->y = 9;
    req = foo_send(ev, ev);

    tevent_req_set_callback(req, foo_done, tmp);
    tevent_req_done(req);

}

int main (int argc, char **argv) {

    struct tevent_context *event_ctx;
    struct testA *data;
    TALLOC_CTX *mem_ctx;
    struct tevent_timer *time_event;

    mem_ctx = talloc_new(NULL); //parent
    if (mem_ctx == NULL)
        return EXIT_FAILURE;

    event_ctx = tevent_context_init(mem_ctx);
    if (event_ctx == NULL)
        return EXIT_FAILURE;

    data = talloc(mem_ctx, struct testA);
    data->y = 11;

    time_event = tevent_add_timer(event_ctx,
                                  mem_ctx,
                                  tevent_timeval_current(),
                                  run,
                                  data);
    if (time_event == NULL) {
        fprintf(stderr, " FAILED\n");
        return EXIT_FAILURE;
    }

    tevent_loop_once(event_ctx);

    talloc_free(mem_ctx);

    printf("Quit\n");
    return EXIT_SUCCESS;
}

Output of this example is:

a->x: 10
b->y: 9
c->y: 9

Info

Version 0.9.8 tevent