Как реализовать практичный планировщик оптоволокна?

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

Как предотвратить запуск процессором планировщика, который работает в режиме ожидания/ожидания? Некоторые волокна просто спят, другие ждут ввода от операционной системы.


person Cheery    schedule 19.04.2009    source источник


Ответы (5)


Вам нужно будет мультиплексировать операции ввода-вывода в интерфейс, основанный на событиях (выбор/опрос), чтобы вы могли использовать ОС для ожидания, в то же время имея возможность планировать другие волокна. select/poll имеют аргумент тайм-аута - для волокон, которые хотят спать, вы можете создать приоритетную очередь, которая использует эту опцию select/poll для эмуляции спящего вызова.

Попытка обслуживать волокна, которые выполняют блокирующие операции (вызов чтения/записи/сна и т. д.). напрямую не будет работать, если вы не запланируете каждое волокно в собственном потоке, что не соответствует цели.

См. http://swtch.com/libtask/ для рабочей реализации.

person nos    schedule 28.12.2009
comment
libtask выглядит красиво, но, похоже, он не позволяет явно планировать задачу пользователем (я не смог найти API для предоставления процессора конкретной задаче). Я думаю, что boost::context выглядит более общим, а сверху есть слой под названием boost::fiber, который реализует блокировки между различными задачами. - person lurscher; 15.11.2010

Вероятно, вам следует взглянуть на семейство функций setcontext (http://en.wikipedia.org/wiki/Setcontext). Это будет означать, что в вашем приложении вам нужно будет повторно реализовать все функции, которые могут блокироваться (чтение, запись, сон и т. д.), в асинхронные формы и вернуться к планировщику.

Только «волокно планировщика» будет ожидать событий завершения, используя select(), poll() или epoll(). Это означает, что когда планировщик бездействует, процесс будет находиться в состоянии ожидания в вызове select/poll/epoll и не будет занимать ЦП.

person Community    schedule 04.05.2009
comment
Как setcontext сравнивается с реализацией всего этого, вообще не полагаясь на машинный стек? Я мог бы поставить сопрограммы ждать, пока другая сопрограмма не остановится, чтобы имитировать простой вызов. - person Cheery; 04.05.2009

Хотя немного поздно отвечать, я хотел бы упомянуть, что у меня есть практическая реализация библиотеки волокон на C, которая называется libevfibers.

Несмотря на то, что это молодой проект, он используется в производстве. Он обеспечивает решение не только для классических асинхронных операций, таких как чтение/запись сокета, но также неблокирует операции ввода-вывода файловой системы. В проекте используются 3 замечательные библиотеки --- libcoro, libev и libeio.

person Lupus    schedule 05.10.2014

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

Хороший пример доступен здесь: Boost Stackful Корутины

person schoetbi    schedule 20.10.2014

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

Спящее/ожидающее волокно просто означает, что оно не запланировано в данный момент — вместо этого оно просто переключается на цикл событий.

Кстати, если вы ищете реальный код, взгляните на http://svn.cmeerw.net/src/nginetd/trunk/, который по-прежнему работа в процессе, но пытается внедрить планировщик волокна поверх многопоточного цикла событий (с портами завершения ввода-вывода Win32 или epoll, запускаемым по краю в Linux).

person cmeerw    schedule 20.04.2009