gelraen
10.04.2012 06:00 imax
Псач, у меня есть тупой вопрос. Мне надо сделать в API как блокирующие, так и неблокирующие операции над сокетом. Как кошернее всего это сделать: ставить/убирать O_NONBLOCK когда надо или же перед операциями которые не должны блокировать дёргать poll(2) на сокет?
в неблокирующем апи тебе нужно давать юзеру функцию process_events(). И сразу же, для удобства, run_event_loop(), для запуска из выделенного треда.
если делать свой run_event_loop(), то в нём придётся делать callback-и на получение сообщений, что светит ненужными костылями как в коде либы, так и в коде её использующем.
ну а как ты иначе сделаешь доставку сообщений в неблокирующем апи? Колбеки. Либо можешь обернуть их в абстракцию вроде deferred values, как в twisted — но колбеки будут пересекать границу твоего интерфейса энивей. Либо же клиент будет вынужден делать поллинг событий.
В любом случае, асинхронное апи обязательно влечёт с собой event loop, передача control flow которому будет либо внутри твоей либы (говно), либо делегирована пользователям либы.
Алсо, вот тебе пример либы, предоставляющей и блокирующие, и неблокирующие апи: http://libusb.sourceforge.net/api-1.0/
Ну, поллинга вида "пришло чо?" в моём случае должно быть достаточно.
поллинг вида «обработай там чо» выглядит точно так же, но предоставляет либе больший decoupling. Алсо, сейчас достаточно @ потом будет поздно. (и libusb здесь тоже охуенный пример: версия 1.0 переделана с учётом всех косяков в предыдущем апи. полезно посмотреть на уроки)
ммм.... не вижу проблемы приделать callback-и позже, не меняя имеющийся API. Пара новых функций и некоторые изменения в приватных структурах, которые не влияют даже на ABI.
в самом крайнем случае приложение может открыть сокет само и просто использовать функции парсинга сообщений из либы
совсем хуевый decoupling какой-то...
алсо, теперь совсем уже интересно, как успешные™ софтоинженеры дизайнят либы, реализующие какой-то протокол поверх другого. Просто функции парсинга неок, ими не сделаешь надёжно state в протоколе и те же таймауты. Правда, если протокол их не юзает и юзать не будет — то понятно, что ок.
стейтов, по сути, у меня нет, есть только запрос-ответ. таймаутов тоже нету. Протокол, по сути, работает с сообщениями, а не потоками байтиков, SOCK_STREAM был выбран только для удобства, чтобы не приходилось хардкодить ограничение на размер сообщения и можно было читать заголовок, выделить кусок памяти и прочитать всё остальное.