Reputation: 64266
we were talking about function and multithreading with my friend. The sample code was:
void SomeClass::Foo()
{
std::lock_guard<std::mutex> lock(mMutexObj);
statement1;
statement2;
statement3;
}
So, we know, that sometimes compiler inlines the functions where it's needed. Is it possible in such case: compiler inlines the Foo
function, all the 3 statements run and lock_guard
doesn't work because scope doesn't end here and no destructor called:
// Inlined operations
std::lock_guard<std::mutex> lock(mMutexObj);
statement1;
statement2;
statement3;
// Global scope, where function was inlined continues here...
global statement1;
global statement2;
...;
Is it possible? What percent that compiler will inline such function or maybe I don't understand right the scope of inlined function?
Upvotes: 0
Views: 2035
Reputation: 129344
Just to answer the question about "what percentage compilers will inline something like this". Given a "release" build (that is, a build with high optimisation level), I'd expect all modern, high quality compilers to inline this code assumeing that statement
doesn't resolve to something VERY large (e.g. in turn inlining a function that inlines another function that inlines a third function).
I know for a fact that GCC will inline a static function that is only called once, even if it's HUGE, because it essentially removes a few instructions, even if the whole "base" function gets several kilobytes larger.
And compilers inline small functions whenever the compiler deems it "of benefit", which is of course a stretchy term. But you can pretty much rely on something that only does a few simple things like add a few integers together, index into a vector or array, etc, to be inlined. If the function is a bit more complex, e.g. has a few loops or several calls to other functions, the chances goes down a bit.
And of course, virtual functions don't get inlined unless it's "obvious" that what the object is.
Upvotes: 2
Reputation: 8886
The effect you describe would happen if you were to use #define
s/macros, but not using inline
. In fact, I believe one of the reasons that inlining was introduced was to avoid the carnage caused by improper use of #define
.
I believe the scope is preserved, using a method equivalent to using {
and }
.
// Inlined operations
{ //curly braces create a scope
std::lock_guard<std::mutex> lock(mMutexObj);
statement1;
statement2;
statement3;
}
// Global scope
global statement1;
global statement2;
...;
Note the use of curly braces above. This is perfectly valid code, and I tend to use it when I have to lock/unlock a mutex at multiple points within a single function. I guess the compiler does something similar with inline functions.
Upvotes: 4
Reputation: 21763
The observable behavior of the program won't change if a function is inlined or not, or declared inline or not. lock_guard's destructor will be called at the appropriate place in either case. Likewise a static variable in a function refers to the same one, even if it's inline(d) or not.
Upvotes: 9