Jump to content
  • Advertisement
Sign in to follow this  
Zael

Threading behavior changes with optmizations

This topic is 2480 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am having an issue with some code I have written, and was wondering if anybody had the depth of knowledge to explain what is happening, and how to avoid it. Here is some example code to demonstrate.

#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
namespace std
{
typedef boost::thread thread;
};
class Thread
{
private:
std::thread* thrd;
int x;
public:
Thread()
{
thrd = NULL;
x = 0;
}
~Thread()
{
if(thrd != NULL)
{
thrd->join();
delete thrd;
}
};
void start()
{
thrd = new std::thread(&Thread::run, this);
};
void join()
{
thrd->join();
thrd = NULL;
};
virtual void run()
{
while(x!=-1)
{
if(x == 1)
{
std::cout << "Got here.\n";
x = -1;
}
}
};
void setX(int x)
{
this->x = x;
}
};
int main()
{
Thread thrd;
thrd.start();
int x;
thrd.start();
std::cin >> x;
thrd.setX(1);
thrd.join();
}


The "Got here." text is displayed twice (which I don't quite understand) when no optimizations are set; however, when I set -O, -O1, or -O2, the program never makes it into the if and hangs forever. Anybody know why that would be?

Thanks

P.S. Using MinGWx64 and Boost 1.48.

Share this post


Link to post
Share on other sites
Advertisement
Well, for one you call thrd.start() two times. This creates two internal thrd instances.
This displays the text twice (every instance of the internal thrd runs into run).

The optimizer probably saw that x is not changed from inside the run function and optimized the checks away. To notify to the compiler, that x may be changed externally, mark it as volatile. This way the compiler will expect the variable to be changed from outside the function as well and not treat it as constant.

Share this post


Link to post
Share on other sites
Duh... Thanks for pointing out that I called thrd.start() twice... completely missed that (It was late). I did not know about using the volatile keyword . That sounds like exactly what I was looking for.

Thanks!

Share this post


Link to post
Share on other sites
Don't rely on volatile for that. It means different things to different compilers. In particular it means different things to GCC (such as MinGW) and Visual C++.

If you want to wait for something, use a condition variable (which boost provides). If you really need to busy-wait/poll (and you probably don't), use your platform's/compiler's interlocked/atomic intrinsics.

EDIT: and your Thread::join() function has a memory leak. Consider using e.g. boost::scoped_ptr.

Share this post


Link to post
Share on other sites
You may also want to make your Thread class uncopyable by privately inheriting from boost::noncopyable, because IF you were to copy an instance of Thread, hilarity would ensue as your class does not honor the rule of three (that, and it probably doesn't make sense to copy a 'Thread' anyhow).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!