views:

829

answers:

10

I make the following reasoning, please tell me what's wrong (or right) about it:

"If inlining a function duplicates the code in the place the function is called, then the static and local variables are duplicated for each function calling it and if there is only one thread running the function that calls the inlined one at the same time, then the code is thread-safe".

"And, if it doesn't help with static and global variables, does it with code that is creating temporary variables?"

Thanks

+26  A: 

Nope, you are wrong. For a static variable, whether it is inlined or not, there is only actually one instance. Inlined functions have no effect on thread safety, one way or the other.

anon
+2  A: 

There are (or perhaps were) buggy compilers that duplicate static variables for each inlining of the containing function. This is not intended behaviour.

With a standart-compliant compiler you are guaranteed to have one instance of each static variable regardless of inlining and have to take care of thread-safety yourself.

sharptooth
+21  A: 

When you declare a function as inline, it is merely a hint to the compiler. Static variables have a clear definition in the language. If the compiler does inline the function, it is still obligated to keep the static variables shared between all instances of the function. Therefore, they will remain global and have to be protected in a MT environment.

As to the local variables, unless they are used outside of the function, they are thread safe regardless of the function being inlined or not.

eran
inline declaration may be a hint, however __forceinline is forced in MSVC ;)
RandomNickName42
+6  A: 

Each thread gets its own copy of the local objects hence there can not be any threading related issues with them whether you make it inline or not.

But if you are accessing a static or a member variable of the class, all the issues related to the multithreading (corrupting the variable, lost updation...) will still be there irrespective of whether it is inline or not.

Naveen
+1  A: 

inlining has no effect on whether or not a function is thread safe. For example:

inline void doTheThing()
{
   int a = 42; // this is thread safe, but it would be anyway
   vector<int> * answers = getTheAnswers(); // this is not thread safe
}

The access to the vector pointed to by getTheAnswers() is not thread safe because there is no code preventing any other thread from executing the code. Making the function inline does not prevent doTheThing() from being called by multiple threads at the same time. In order to make doTheThing() thread safe, you need to make sure that either it is not called in parallel, or any shared (non-local) data you do access is protected.

John Dibling
I didn't say it was thread unsafe; I said it was not thread safe. That's not splitting hairs. Understanding the difference between thread safe, unsafe, and not safe is the difference between people who grok multithreading and people who dont.
John Dibling
Unless you know the implementation of getTheAnswers(), you can't say it is thread safe. The signature implied by the call (vector<int>* getTheAnswers;) certainly doesn't suggest that it is.
John Dibling
OK, then it does suggest something to you -- that it allocates a vector and returns it. Which may or may not be true. But even if it were true, how does it do that? Does it copy elements from some global vector? Is that global vector's access made thread safe? The point is: you don't know.
John Dibling
*sigh* yourself, read my original post. "In order to make doTheThing() thread safe, you need to make sure that either it is not called in parallel, or any shared (non-local) data you do access is protected."
John Dibling
+2  A: 

Thread safety has nothing to do whatsoever with inlining. Just because each thread executes a copy of the same code does not make it safe to access shared data. Please make sure to read up on Thread safety before you start multi threaded programming.

lothar
not useful answer.
alvatar
Why? The only way to program thread safe is to learn about thread safety. And from what I can see my answer is as of now still the only one that provides you with a link to some reading to get a deeper understanding of the matter.
lothar
Yes, you are right that you give me a link. But for a wikipedia article on thread-safe I don't need to ask in SO. Besides, I ask for the reasons. Anyway, I removed my downvote.
alvatar
+2  A: 

If I were you, I would not use static variables within inline functions. Older versions of the C++ standard called for a different meaning than the current one.

Joshua
A: 

Not at all.

In order to be thread-safe, a function needs to be thread-safe with respect to ANY instance of the function, including itself; multiple threads can execute the same instance of an inlined function at the same time.

Therefore, even if the compiler did what you suggested (which it shouldn't, as others have said), that would still not make it thread-safe.

MarkR
A: 

All static variables in (normal and inline) functions go into heap. Heap is NOT THREAD SAFE.

Alphaneo
+3  A: 

Inlining and thread safety are orthogonal, i.e. unrelated concepts.

Consider these functions:

int factorial(const int n)
{
  if (n <= 1)
  {
    return 1;
  }

  return factorial(n - 1);
}

This function cannot be inlined since it is recursive, yet it is perfectly thread-safe.

int factorial_2(int n)
{
  int Result = 1;

  while (n > 1)
  {
    Result *= n--;
  }

  return Result;
}

This function could be inlined by the compiler, and is still perfectly thread-safe.

int RefCount;

void DecRef()
{
  --RefCount;
}

This function is not thread-safe regardless whether the compiler inlines it or not.

Tobias
thanks for this late response :). I have clear concepts in my mind now, but your code is very illustrative. Thanks!
alvatar
It's been a pleasure :)
Tobias