Поддерживает ли Boost поддержку Windows EnterCriticalSection API?
Я знаю, что в Boost есть поддержка мьютексов и lock_guard, которые можно использовать для реализации критических секций.
Но в Windows есть специальный API для критических разделов (см. EnterCriticalSection и LeaveCriticalSection), который является ОЧЕНЬ большим, чем мьютекс (для редко оспариваемых коротких разделов кода).
Отсюда мой вопрос - возможно ли в Boost воспользоваться этим API, и отступить к реализации на основе spinlock/mutex/futex на других платформах?
3 ответа
Таким образом, похоже, что мьютекс Boost по умолчанию не поддерживает его, но asio::detail::mutex
делает.
В итоге я использовал это:
#include <boost/asio/detail/mutex.hpp>
#include <boost/thread.hpp>
using boost::asio::detail::mutex;
using boost::lock_guard;
int myFunc()
{
static mutex mtx;
lock_guard<mutex> lock(mtx);
. . .
}
Простой ответ - нет.
Вот некоторые важные сведения из старой ветки списка рассылки:
КСТАТИ. Я согласен, что мьютекс является более универсальным решением от
с точки зрения производительности. Но если быть честным - CS быстрее в простом дизайне. Я считаю, что возможность поддержать их должна быть по крайней мере принята во внимание.
Это была статья, на которую кто-то указал мне. Был сделан вывод, что CS быстрее, только если:
- Всего в процессе менее 8 потоков.
- Вы не бегали в фоновом режиме.
- Вы не были на двухпроцессорной машине.
Для меня это означает, что простое тестирование дает хорошие результаты производительности CS, но любая реальная программа лучше использовать полноценный мьютекс.
Я не против поддержки реализации CS. Однако изначально я решил не делать этого по следующим причинам:
- Вы получаете либо удар по строительству и разрушению при использовании идиомы PIMPL, либо вы должны включить Windows.h в заголовки Boost.Threads, чего я просто не хочу делать. (Это можно обойти, эмулировав OPTEX CS ala от MSDN.)
- Согласно этой исследовательской работе, большинство программ не получат выгоду от дизайна CS.
- Тривиально кодировать (непереносимый) класс критической_секции, который следует модели Mutex, если вы действительно можете использовать это.
Сейчас я думаю, что сделал правильный выбор, хотя в будущем мы можем изменить реализацию, чтобы использовать критический раздел или OPTEX.
Билл Кемпф
Говоря как кто-то, кто помогает поддерживать Boost.Thread, и как человек, которому не удалось получить объект события в Boost.Thread, я не думаю, что критические разделы когда-либо были добавлены и не будут добавлены в Boost по следующим причинам:
Критический раздел Win32 тривиально легко построить с использованием boost::atomic и boost::condition_variable, настолько, что не стоит иметь официальный. Вот, пожалуй, самый сложный из всех, что вы только можете себе представить, но чрезвычайно настраиваемый, включая готовность к const expr (не спрашивайте!): https://github.com/ned14/boost.outcome/blob/master/include/boost/outcome/v1/spinlock.hpp#L331
Вы можете создать свой собственный, просто сопоставив (Basic) блокируемую концепцию и используя atomic compare_exchange (не x86/x64) или atomic exchange (x86/x64), а затем захватите его с помощью lock_guard вокруг критической секции.
Некоторые могут возразить, что критический раздел win32 - это не так. Боюсь, что так оно и есть: он просто вращается на атоме для подсчета вращения, а затем лениво пытается выделить объект события win32, который затем ожидает. Ничего особенного.
Сколько бы вы ни думали, что критические секции (действительно мьютексы в режиме пользователя) лучше / быстрее / чем угодно, они, вероятно, не так хороши, как вы думаете. boost::mutex - это большая и тяжелая вещь для Windows, использующая семафор win32 в качестве объекта ожидания ядра из-за необходимости эмулировать отмену потоков и вести себя хорошо в контексте общего назначения. Легко написать структуру параллелизма, которая быстрее, чем другая, для какого-то одного случая использования, но очень и очень трудно написать структуру параллелизма, которая состоит из:
- Быстрее, чем стандартная реализация в неконтролируемом случае.
- Быстрее, чем стандартная реализация в слегка оспариваемом случае.
- Быстрее, чем стандартная реализация в значительной степени утверждали случае.
Даже если вам удастся справиться со всеми тремя вышеперечисленными действиями, этого все равно недостаточно: вам также нужны некоторые гарантии для наихудшего порядка упорядочения прогрессии, чтобы обеспечить предсказуемые результаты при определенных схемах блокировок, ожиданий и разблокировок. Вот почему средства потоков могут выглядеть медленными в узких сценариях сценариев использования, так что Boost.Thread, так как STL может показаться намного медленнее, чем код блокировки, свернутый вручную, например, в случае непреднамеренного использования.
Boost.Thread уже выполняет существенную работу в пользовательском режиме, чтобы избежать перехода в спящий режим ядра в Windows. В POSIX любая из основных реализаций pthreads также выполняет значительную работу, чтобы избежать сбоев ядра и, следовательно, Boost.Thread не воспроизводит эту работу. Другими словами, критические разделы ничего не выигрывают с точки зрения масштабирования для загрузки поведения, хотя неизбежно Boost.Thread v4, особенно в Windows, выполняет большую часть работы, которую не делает наивная реализация (запланированное переписывание Boost.Thread значительно более эффективен на Windows, поскольку это может предполагать Windows Vista или выше).