Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libev c++ wrapper function_thunk

Tags:

c++

void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw ()
{
  this->data = (void *)data;
  ev_set_cb (static_cast<ev_watcher *>(this), cb);
}

// function callback
template<void (*function)(watcher &w, int)>
void set (void *data = 0) throw ()
{
  set_ (data, function_thunk<function>);
}

template<void (*function)(watcher &w, int)>
static void function_thunk (EV_P_ ev_watcher *w, int revents)
{
  function
    (*static_cast<watcher *>(w), revents);
}

Hi,

I'm using libev's C++ wrapper ev++.h. There is this piece of code in ev++.h that I know how to use as an API, but don't fully understand. I can set up a Ctrl-C watcher in the event loop as follows:

ev::sig signal_watcher(evloop); 
signal_watcher.set<sigint_cb>(); 
signal_watcher.start(SIGINT); 

where sigint_cb's function signature is :

void sigint_cb(ev::sig &w, int revents)

Can someone explain why function_thunk can magically cast my sigint_cb function signature to

void (*cb)(EV_P_ ev_watcher *w, int revents)

What C++ sorcery is this? Thanks.

like image 402
lppier Avatar asked Apr 11 '16 07:04

lppier


1 Answers

function_thunk doesn't magically cast sigint_cb signature to void (*cb)(EV_P_ ev_watcher *w, int revents) it just call sigint_cb with properly casted arguments.

From the beginning, function_thunk is a function template which can be intstantiated with function pointer of type void (*)(watcher &w, int). So basically when you will write function_thunk<sigint_cb> somewhere in your code, compiler will create corresponding function_thunk instance which will be looking like this:

void function_thunk (EV_P_ ev_watcher *w, int revents)
{
    sigint_cb(*static_cast<watcher *>(w), revents);
}

Also note that in you example ev::sig and watcher are the same types, otherwise template argument deduction/substitution for function_thunk would failed.

like image 157
Anton Shakhmut Avatar answered Sep 29 '22 19:09

Anton Shakhmut