Продолжение темы (часть 1, часть 2, часть 3, часть 4).
К своему стыду не знал, что в Windows 7 появилась весьма интересная штука: User-Mode Scheduling. Между тем, для реализации акторов в виде последовательных функций, а не в виде конечных автоматов, это очень интересная штука.
Как я понял после поверхностного ознакомления, механизм UMS (User-Mode Scheduling) работает по следующему принципу:
Пользователь определяет отдельную нить в качестве UMS-диспетчера. Для выполнения диспетчерских функций пользователь должен написать функцию-диспетчер, указатель на которую передается Windows при переводе нити из разряда обычных нитей в разряд UMS-диспетчеров. Windows будет сама вызывать эту функцию-диспетчер для уведомления о том, что произошло какое-то важное для UMS-диспетчера событие.
Пользователь определяет отдельные UMS-нити, которые будут использоваться в качестве рабочих. Эти нити связываются с UMS-диспетчером. Диспетчеризацией таких нитей занимается не ядро Windows, а UMS-диспетчер.
Привлекательность этого подхода в сравнении с подходом Boost.Fibers (см. презентацию из предыдущей заметки) состоит в том, что рабочие UMS-нити могут использовать обычные Windows-примитивы и обычные системные вызовы Windows. Если UMS-нить блокируется каким-то системным вызовом (например, засыпает не ожидании события/мутекса или на синхронной операции ввода-вывода), то Windows уведомляет об этом UMS-диспетчер. Мол, такая-то из твоих рабочих нитей заблокирована, можно дать управление кому-то другому. Что позволяет UMS-диспетчеру толкнуть на исполнение любую из других подчиненных ему UMS-нитей. Когда ранее заблокированная UMS-нить разблокируется (например, операция ввода-вывода завершилась), то Windows пришлет в UMS-диспетчер уведомление о том, что нить может продолжать свою работу и UMS-диспетчер может либо толкнуть ее на выполнение, либо сохранить в своем списке готовых для запуска нитей.
Получается, что рабочие UMS-нити можно писать точно так же, как и обычные нити: без оглядки на то, что вместо обычного мутекса нужно использовать какой-то псевдомутекс, что синхронные IO-операции дергать нежелательно и т.д. Тогда как при использовании Boost.Fiber нужно об этом всем думать (т.е. задействовать boost::fiber::mutex вместо std::mutex, boost::fiber::promise вместо std::promise и т.д.).
А это означает, что UMS позволяет оформлять обычные последовательные функции, с обычными системными вызовами Windows, в виде акторов, диспетчеризация которых осуществляется посредством своего собственного диспетчера.
Что выглядит очень круто. Но, похоже, непереносимо на другие платформы. Даже на 32-х битовый Windows :)
Комментариев нет:
Отправить комментарий