вызывая Кевента силой - PullRequest
       24

вызывая Кевента силой

2 голосов
/ 28 июля 2010

Я использую kqueue для синхронизации сокетов в OS X. Я могу зарегистрировать интересующее событие, как показано ниже:

struct kevent change;
EV_SET(&change, connected_socket, EVFILT_READ, EV_ADD, 0, NULL, NULL);
kevent(k_queue_, &change, 1, NULL, 0, NULL);

И вопрос в том, есть ли способ вызвать это событие принудительночтобы ожидающий вызов kevent вернулся?

Ответы [ 3 ]

2 голосов
/ 28 июля 2010

Некоторые возможности, кроме естественной записи данных на другую сторону сокета:)

  • shutdown(2) сторона чтения этого сокета - вы получите EV_EOF в flags(глупо),
  • Используйте аргумент тайм-аута и вызовите ту же самую функцию обработки,
  • Используйте трюк с самоотводом , когда вам нужно прервать ожидание.

Хотя мой вопрос: зачем вам это?

Редактировать:

Если я правильно понимаю ваши комментарии, вы ищете способ обойти поведение, инициируемое краем (EV_CLEAR) для записи событий.Я считаю, что правильный способ сделать это - отменить регистрацию вашего сокета с EVFILT_WRITE, когда у вас ничего нет в исходящей очереди, а затем заново зарегистрировать его, когда есть данные для отправки.Это немного больше работы, но вот как это работает, и вам не нужны дополнительные системные вызовы, так как kevent(2) принимает как изменения, так и результаты.Посмотрите на libevent и посмотрите, как он справляется с такими вещами.И вы используете неблокирующие розетки, верно?

1 голос
/ 02 июля 2015

OSX 10.6 и FreeBSD 8.1 добавляют поддержку EVFILT_USER, которую мы можем использовать для пробуждения цикла событий из другого потока.

Обратите внимание, что если вы используете это для реализации своих собственных условий и времени ожидания, вам все еще нужны блокировки, чтобы избежать условий гонки , как объяснено в этого превосходного ответа .

См. Мой другой ответ для полного примера кода: https://stackoverflow.com/a/31174803/432

1 голос
/ 05 марта 2012

Я бы порекомендовал немного другое решение.

Добавьте еще одно зарегистрированное событие в kqueue.В частности, EVFILT_USER.

Вы можете использовать это для запуска любого поведения, для которого вы хотите разбудить поток kevent () без кода, выглядящего странно или сложного для поддержки.

Исходники OSX имеютнастоящий грубый тест для него в

http://www.opensource.apple.com/source/xnu/xnu-1699.24.23/tools/tests/xnu_quick_test/kqueue_tests.c

...