views:

113

answers:

6

Suppose I have my own non-inline functions LockMutex and UnlockMutex, which are using some proper mutex - such as boost - inside. How will the compiler know not to reorder other operations with regard to calls to the LockMutex and UnlockMutex? It can not possibly know how will I implement these functions in some other compilation unit.

void SomeClass::store(int i)
{
  LockMutex(_m);
  _field = i;  // could the compiler move this around?
  UnlockMutex(_m);
}

ps: One is supposed to use instances of classes for holding locks to guarantee unlocking. I have left this out to simplify the example.

A: 

If compiler was doing so that'd be a bad compiler. ;-)

AlexanderVX
+2  A: 

In general, a compiler will not move code around unless it knows with certainty that doing so will not affect run-time behavior.

500 - Internal Server Error
Correct. A code motion compiler will have a static analysis model of how your program operates and its data/operational dependencies, and it will preserve those dependencies.
Paul Nathan
Strictly speaking, there is not any dependency between the _field variable, say, and the call to LockMutex or UnlockMutex, so preserving dependencies don't help here.
Diego Sevilla
A: 

If the compiler can't guarantee that the function calls won't have side effects that will modify the variables between the calls, it can't move the code. If the variable is a local variable and you've never taken a reference or created a pointer to it, the compiler might assume it's safe to move; I don't know.

Mark Ransom
If the variable is local, isn't volatile, and has not had a pointer or reference taken, no other thread can access it. So as far as taking a mutex is concerned, it wouldn't matter if the store happens before, after or between the function calls or if it never occurs.
Michael Burr
@Michael Burr, isn't that what I said? If the compiler is sophisticated enough, it might determine that a local variable load/store is safe to reorder; whether it does or not probably depends on optimizer settings. I was looking beyond the confines of the question where it is obvious the variable is *not* local. As asked, it falls under my first sentence - the compiler has no way of knowing the side effects of LockMutex or UnlockMutex, so it can't reorder.
Mark Ransom
@Mark: I wasn't disagreeing; I thought I was clarifying something that seemed to be uncertain at the end of the answer. I didn't mean for it to sound argumentative if that's how it came across.
Michael Burr
+1  A: 

As it is written, if the functions are not inline, the compiler won't move the variable assignation, as the call may be unrelated to the _field variable, but it has to preserve the strict order of calls. If, however, the compiler decides to inline the calls, I think it will treat them as blocks of independent code, that is, it will only reorder instructions within the same code unit (the inlined function itself) but not with the following or preceding code (the assignation to the _field variable).

Diego Sevilla
Thanks. Do you have a link to documentation stating that compiler reordering stops at boundaries of even inline functions?
shojtsy
+1  A: 

You're right, that code is correct and safe. I did think of a "code joke," though.

pthread_mutex_lock( &mx ) + foo() + pthread_mutex_unlock( &mx );
Potatoswatter
+2  A: 

It can not possibly know how will I implement these functions in some other compilation unit.

This is the key - since the compiler cannot know (in general) about the implementation of the function calls, it can't move the store to _field outside those function calls.

Generally, since _field is accessible outside of SomeClass::store() (it's not a local), the compiler can't know whether or not it's modified by the external function, therefore it must perform the store to _field between the function call sequence points.

The underlying hardware platform might need some attention in the form of memory barriers or cache flushes to deal with caching or out of order operations that occur in the hardware. The platform's implementation of the mutex APIs will deal with those issues if necessary.

Michael Burr