Max Frai
Max Frai

Reputation: 64266

Mutex and inline function

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

Answers (3)

Mats Petersson
Mats Petersson

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

maditya
maditya

Reputation: 8886

The effect you describe would happen if you were to use #defines/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

Neil Kirk
Neil Kirk

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

Related Questions