Вы говорите, что libev предоставляет вам только ограниченный объем данных - сам дескриптор ev_io
- и делаете вывод, что все, что здесь полезно, - это дескриптор файла.Ну, как правило, вы, вероятно, правы, но есть хитрый прием, который вы можете сделать.
Поскольку с libev вы выделяете структуры самостоятельно, а затем имеете libev, инициализируете их, ничто не мешает вам выделить слишком много места.Так как libev не будет касаться этого дополнительного пространства, вы можете поместить туда свои собственные вещи.Удачи!
Так как же это работает на практике?Вы создаете новую структуру, содержащую ev_io
в качестве первого члена, а затем помещаете все остальные данные после него, скажем так:
struct my_mutant_io {
ev_io handle;
int group_id;
};
Теперь, где бы вы ни выделяли uv_io
,выделите my_mutant_io
вместо этого.Поместите ваши данные туда, куда вы хотите, и как только вам нужно будет передать их в функцию libuv, просто возьмите вместо этого адрес handle
:
struct my_mutant_io *mutant = malloc(sizeof(struct my_mutant_io));
if(!mutant) {
abort();
}
mutant->group_id = /* ... */;
ev_io_init(&mutant, some_callback, fd, EV_READ);
Вы дали libev ev_io
и не удивительно, что на самом деле это просто часть большей структуры.Теперь давайте перейдем к обратному вызову.Ты вернешь свой ev_io
, но подожди!Поскольку ev_io
является первым членом структуры, его адрес совпадает с адресом нашего мутанта.Мы можем привести ev_io *
обратно к struct my_mutant_io *
и использовать его.(Только не говорите строгим псевдонимам богов.)
Структуру, подобную этой, чаще всего называют дубинкой.