Периодически вызывать функцию C без создания потока вручную - PullRequest
1 голос
/ 15 ноября 2011

Я реализовал обработчик WebSocket в C ++, и мне нужно время от времени отправлять сообщения ping.Однако я не хочу запускать один поток на сокет / один глобальный поток опроса, который вызывает только функцию ping, но вместо этого использую некоторые функции ОС для вызова моей функции таймера.В Windows есть SetTimer, но для этого требуется рабочий цикл сообщений (которого у меня нет.) В Linux есть timer_create, который выглядит лучше.метод, чтобы получить функцию, вызываемую периодически, в идеале с некоторым пользовательским контекстом?Т.е. что-то вроде settimer (const int millisecond, const void* context, void (*callback)(const void*))?

[ Edit ] Просто чтобы прояснить ситуацию: я не хочу управлять дополнительными потоками.В Windows, я думаю, использование CreateThreadpoolTimer в пуле системных потоков поможет, но мне интересно узнать, есть ли более простое решение и как перенести это на Linux.

Ответы [ 4 ]

1 голос
/ 15 ноября 2011

Если вы собираетесь использовать кроссплатформенность, я бы предложил вам использовать кроссплатформенную библиотеку событий, например libevent .

libev новее, однако в настоящее время имеет слабую поддержку Win32.

0 голосов
/ 15 ноября 2011

Всякий раз, когда у вас есть асинхронные события, у вас должен быть цикл обработки событий.Это не обязательно должно быть системное значение по умолчанию, например, цикл сообщений Windows.Вы можете создать свой собственный.Но вы должны его использовать.

Весь смысл программирования, основанного на событиях, заключается в том, что вы не используете свою обработку кода для работы с четко определенными функциональными фрагментами, основанными на этих асинхронных событиях.Без цикла обработки событий вы обрекаете себя на чередование кода, который получает входные данные и производит выходные данные на основе плохо определенных «состояний», которые являются просто фрагментами процедурного кода.

Без четко определенного разделения состояний с использованием событияна основе дизайна, код быстро становится неуправляемым.Поскольку код делает паузы внутри процедур для выполнения входных задач, у вас есть время жизни объектов, которое не будет охватывать целые области действия процедур, и вы начнете писать if (nullptr == xx) в различных местах, которые обращаются к объектам, созданным или уничтоженным на основе событий.Диспетчеризация становится комбинаторно сложной, потому что в каждой точке ввода ожидаются разные события и нет абстракции.

Однако, просто используя цикл обработки событий и диспетчеризацию для конечных автоматов, вы уменьшили сложность обработки до базового управления обработчиками (O(n) обработчики против операторов ветвей O (mn) с n типами событий и m состояниями).Вы отделяете обработку, но все еще допускаете изменение функциональности в зависимости от состояния.Но теперь эти состояния четко определены с использованием классов состояний.И новые состояния могут быть добавлены, если требования продукта меняются.

Я просто говорю, перестаньте пытаться избежать цикла событий.Это программный шаблон по очень важным причинам, все из которых связаны с созданием профессионального, многократно используемого, масштабируемого кода.Используйте Boost.ASIO или какой-либо другой фреймворк для кроссплатформенных возможностей.Не становитесь привычкой делать это неправильно только потому, что думаете, что это будет меньше усилий.В конце концов, даже если это не профессиональный проект, который требует длительного сопровождения, вы хотите попрактиковаться в том, чтобы сделать свой код профессиональным, чтобы вы могли что-то сделать со своими навыками.

0 голосов
/ 15 ноября 2011

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

Первая причина в том, что она совершенно опасна.Это похоже на написание многопоточного приложения с абсолютно без синхронизации .Вторая причина заключается в том, что очень сложно иметь хорошую семантику в многопоточных приложениях.Какой поток должен выполнить обратный вызов таймера?

Если вы пишете обработчик веб-сокета, вы, вероятно, уже пишете цикл на основе select().Если это так, то вы можете просто использовать select() с коротким таймаутом и проверять различные соединения, для которых вам нужно пропинговать каждого пира.

0 голосов
/ 15 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...