Given the following example code:
int var;
int mvar;
std::mutex mvar_mutex;
void f(){
mvar_mutex.lock();
mvar = var * var;
mvar_mutex.unlock();
}
I want to express that mvar_mutex
is bound to the variable mvar
and protects only that variable. mvar_mutex
should not protect var
because it is not bound to it. Hence the compiler would be allowed to transform the above code into the below code:
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();
}
This might reduce contention on the lock as less work is being done while holding it.
For int
this can be done using std::atomic<int> mvar;
and removing mvar_mutex
, but for other types such as std::vector<int>
this is not possible.
How do I express the mutex-variable binding in a way that C++ compilers understand it and do the optimization? It should be allowed to reorder any variable up or down across mutex boundaries for any variable that is not bound to that mutex
Since the code is being generated using clang::ASTConsumer
and clang::RecursiveASTVisitor
I am willing to use non-standard extensions and AST manipulations as long as clang (ideally clang 4.0) supports them and the resulting code does not need to be elegant or human-readable.
Edit since this seems to be causing confusion: The above transformation is not legal in C++. The described binding of mutex to variable doesn't exist. The question is about how to implement that or achieve the same effect.