tevent_data(3)

πŸ“¦
version 0.17.1 Β· 2 versions
, in centos-stream 10, fedora 43, fedora 44, opensuse-leap 16.0

🌸 tevent_data β€” Chapter 3: Accessing data πŸ’–

okay bestie, welcome to tevent_data from the tevent library functions manual β€” this is the chapter on getting your lil hands on data. sit down, grab a strawberry matcha, we're doing pointers today and honestly? it's giving iconic. πŸ“βœ¨


✨ Accessing data with tevent ✨

so like, a tevent request is (usually) created together with a structure for storing the data you need for an asynchronous computation. classic. 🫢

for these private data, the tevent library uses void (generic) pointers, which means literally any data type can be pointed at, super simply, no drama. BUT β€” and this is the part where you have to lock in πŸ”’ β€” that attitude requires clear and guaranteed knowledge of the data type that will be handled, in advance. no vibes-based casting, bestie. you have to know.

private data can be of 2 types:

  1. connected with a request itself, or
  2. given as an individual argument to a callback.

you must differentiate these types, because there's a slightly different method of data access for each one. it's not a vibe thing, it's a real thing. πŸ’…

and listen β€” there are two possibilities for how to access data that's given as an argument directly to a callback. the difference lies in the pointer that is returned:

  • in one case it's 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)

and to obtain data that is strictly bound to a request? this function is the only direct procedure. no shortcuts, no alternate routes, this is the one:

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

🌈 Example: both calls, side by side

here's an example with both calls, which differs between private data within a tevent request and data handed over as an argument. it's a whole serve, honestly. πŸ‘‘

#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

🫢 quick vibe check, bestie: notice how a came from foo_send so it's the request-bound data (tevent_req_data), while b and c are both the callback argument (testA, y = 9) reached two different ways β€” tevent_req_callback_data gives you the typed pointer, tevent_req_callback_data_void gives you the void* and you cast it yourself. same data, different door. πŸšͺ✨

okay that's the whole chapter and you ATE it. πŸ’… this was tevent_data(3) from tevent, Version 0.9.8 β€” mwah, go write some async code, you're the main character of this event loop. πŸ¦‹πŸŒΈπŸ’œ