Учитывая следующий пример кода:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
mvar_mutex.lock();
mvar = var * var;
mvar_mutex.unlock();
}
Я хочу выразить, что mvar_mutex
привязан к переменной mvar
и защищает только эту переменную. mvar_mutex
не должен защищать var
, потому что он не связан с ним. Следовательно, компилятору будет разрешено преобразовать вышеуказанный код в следующий код:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
int r = var * var; //possible data race created if binding is not known
mvar_mutex.lock();
mvar = r;
mvar_mutex.unlock();
}
Это может привести к сокращению конкуренции на блокировке, поскольку при ее проведении выполняется меньше работы.
Для int
это можно сделать с помощью std::atomic<int> mvar;
и удаления mvar_mutex
, но для других типов, таких как std::vector<int>
, это невозможно.
Как выразить привязку переменной mutex в способе, которым компиляторы С++ понимают это и делают оптимизацию? Должно быть разрешено переупорядочивать любую переменную вверх или вниз по границам мьютекса для любой переменной, которая не связана с этим мьютексом
Поскольку код генерируется с использованием clang::ASTConsumer
и clang::RecursiveASTVisitor
, я готов использовать нестандартные расширения и манипуляции с АСТ, если clang (идеально clang 4.0) поддерживает их, и полученный код не должен быть элегантным или читаемым человеком.
Изменить, поскольку это, по-видимому, вызывает путаницу: вышеуказанное преобразование не является законным в С++. Описанная привязка мьютекса к переменной не существует. Вопрос заключается в том, как реализовать это или добиться того же эффекта.