Установка приоритетов потокам
В STL и Boost есть классы для работы с потоками, но устанавливать приоритеты потокам приходится через сторонние библиотеки как pthread. Для каждой ОС этот код разный, хотелось бы иметь стандартные средства для управления приоритетом потока.
std::thread thread([](){ std::cout << "Hello world!" }, std::thread::priority::high_priority);
Тогда уж и для std::jthread надо такое вводить.
А еще подумать, как быть с std::async, так как там задача по стандарту может выполняться в отдельном потоке. Напрашивается вопрос, а почему же и тут тогда приоритет нельзя задать. Интересный момент возникает, если задача не выполняется в отдельном потоке. Тогда меняется приоритет текущего потока или как?
Не думаю, что для std::async нужно устанавливать приоритеты. Вместо std::async лучше использовать std::future/promise. При написании realtime программ нужно некоторым потокам задавать высокий приоритет, так как обработка данных в приоритете над GUI, сейчас нужно для каждой ОС писать собственную реализацию, что очень не удобно.
Любопытная идея. Пока хотелось бы обсудить следующие проблемы:
- Q: Как передавать приоритет в объект потока? A: Первое, что приходит на ум - в конструкторе, т.к. тащить шаблонным параметром, очевидно, нет смысла. Но вдруг пользователь захочет установить приоритет во время выполнения?
- Q: Как сообщить, что установить приоритет не удалось? A: В случае отдельного метода можно выбросить исключение, но такое недопустимо в конструкторе: окажемся в ситуации, когда объект не создан, но реальный поток уже начал выполняться!
Насчёт std::async тоже нужно подумать: хоть она и непопулярна, запуск задачи с background-приоритетом - например, скачивания файла - может быть удобным.
Я не сталкивался с задачей изменения приоритета потока во время его выполнения, обычно заранее известен приоритет задачи. На мой взгляд логично передавать приоритет потока при передаче функтора. Тогда всё выглядело бы просто и понятно.
std::thread thread([](){ ... }, std::thread::priority::high_priority);
и для std::async
auto ret = std::async(std::launch::async, std::thread::priority::high_priority, [](){ ... });
Тогда возвращаемся к вопросу сигнализации о неудаче :) Изменять приоритет потока в ходе работы тоже иногда приходится: например, поток закончил ожидать IO, передает задачу в соседний worker-thread (предположим, что задача небольшая, и пул не требуется), попутно повышая его приоритет
Одно из решений, добавить метод, который будет возвращать текущий приоритет:
std::thread thread([](){ ... }, std::thread::priority::high_priority);
if (thread.priority() != std::thread::priority::high_priority) {
...
}
Не думаю, что неудача установки приоритета это критическая ошибка, что бы кидать исключения или не запускать поток на выполнение, в Linux такое часто происходит, если у программы нет прав root.
Как вариант. Заодно можно сразу реализовать метод bool set_priority(std::thread::priority)
А на всех ли платформах можно установить потоку приоритет? Есть опасения насчет гибкости итогового решения...
Установка приоритета есть на всех ОС, но не на всех можно поднимать до высокого без привилегий. В Qt возможность есть устанавливать приоритет.
Пока я вижу "полторы" проблемы:
- Вопрос привилегий. Но - по крайней мере на Windows - нужные права можно получить при создании потока средствами WinAPI.
- Нюансы с установкой приоритетов для потоков в ядре (да, речь о имплементации
threadв несколько нестандартном окружении). Но это уже лично мои тараканы - практика показывает, что Комитет по стандартизации и С++ ядерщики в разных плоскостях находятся :)