Реализация асинхронного в/в в libmary (epoll).

Основной объект - PollGroup ("группа опроса"), как в MyCpp.

В PollGroup добавляем объекты - fd. Считаем, что одновременно fd может быть
добавлен только в одну группу опроса.

Как хранятся fd в группе опроса? Какими вообще свойствами обладает Connection?
...доступ к одному объекту Connection должен синхронизироваться извне. Это
означает, что Connection не снабжён механизмом подсчёта ссылок, что, в свою
очередь, значит, что членством Connection в PollGroup нужно управлять явно.

В случае с epoll в группе опроса вообще не нужно хранить информацию о
соединениях. Структура данных, описывающая соединение, будет храниться прямо
в ядре (ук-ль на неё).

Для select нужен будет список объектов на опрос, т.е. придётся поддерживать
связный список.

На выходе epoll - события err, hup, rd, wr - блоком. С одним соединением связан
только один блок.

? Как будет построен сам ввод/вывод? Какая модель управления в/в?

Чтение | управляем on/off;
Запись | управляем on/off.

Варианты - ?
...соединение всегда должно быть готово к обслуживанию методов read/write.
...вызовы read/write могут возвращать IoResult_Again.

Если метод чтения вернул Again, то впоследствии должен быть вызван callback
read_ready () - простое правило. Аналогично - с write(). Сигнализирование -
однократное.

Зачем нужно делать setNeedInput() / setNeedOutput()? В описанной схеме - вообще
не нужно. С их помощью можно полностью убрать соединение из списка на опрос
(шейпер?), но зачем это делать? - Явно лишнее усложнение.

Два варианта работы: edge-triggered и level-triggered.
Базовый - level-triggered. Плохо подходит для epoll: если по событию о
готовности на чтение не произошёл eagain, то нужно удалять блокировать событие
для fd. В MyCpp сейчас это сделано крайне неэффективно.

Нужно ли обрабатывать HUP? HUP - значит, что мы не читаем (только пишем),
а удалённый конец "отвалился". Так? То есть "могут быть данные на чтение".

HUP несовместим с OUT - никогда не приходит вместе с ним.

Полагаюсь на то, что можно не делать повторный read(), если пришло меньше
данных. Но для этого нужно ввести дополнительной выходной параметр "again".

