I tried using threads and it worked very well. But I have a little question regarding a mutex. I want the sf::RenderWindow to close when the QT Window closes (or when a button is clicked). This is how I do it:
I created a class that has a Run function, which looks like this:
void CRenderThread::Run()
{
sf::RenderWindow RenderWindow(sf::VideoMode(300, 200), "SFML works!");
sf::Text text("SFML works");
m_bRunning = true;
while (RenderWindow.isOpen() && m_bRunning)
{
sf::Event event;
while (RenderWindow.pollEvent(event))
{
if (event.type == sf::Event::Closed)
RenderWindow.close();
}
RenderWindow.clear();
RenderWindow.draw(text);
RenderWindow.display();
}
RenderWindow.close();
return;
}
The class also has a Exit function which looks like this:
void CRenderThread::Exit()
{
m_bRunning = false;
}
The Run function is the thread function, which I create in main(). The Thread is a public member of my (Qt) QMainwindow. So it looks a bit complicated:
QMainWindow w;
sf::Thread thread(&CRenderThread::Run, &w.RenderThread);
thread.launch();
The reason the Thread is a member of my QMainWindow is, so that I can call the exit function from there (on button click or on close). But my Question is: I obviously need a mutex to secure my m_bRunning from being assigned to false in the wrong moment. But where do I have to put the Lock? Obviously around the false assigment in the exit function, but I cant put the other before the while (RenderWindow.isOpen() && m_bRunning), because the lock would never open until the while loop finishes. And inside the while loop wouldn't make to much sense either, because the m_nRunning lookup already happened.
I don't really know what to do. I hope this is not a stupid question and that I'm not simply missing something. Thanks in advance,
Foaly
A clean solution is to encapsulate it in a (private) function:
bool CRenderThread::IsRunning() const
{
sf::Lock lock(m_mutex);
return m_bRunning;
}
void CRenderThread::Run()
{
...
while (RenderWindow.isOpen() && IsRunning())
{
...
Note that your mutex must be declared as mutable so that it can be locked in a const member function.
If you work with compilers that support the new C++11 standard library, you can also use an atomic int (more efficient and simpler to write).
OK I'll have another look into that :)
Another question (well it's almost the same... :D) : In my thread I draw everything to a RenderTexture. Then of course I use a Sprite to display the RenderTexture in my window. Code looks like this:
mySprite.setTexture(myRenderTExure.getTexture());
window.clear();
window.draw(mySprite);
window.display();
Now I need to change the opacity of that RenderTexture (changing the sprites color), but my question is how do I do this Thread safe? I was gonna use a function, which the gui elements can call, which contains a lock. But how do i make the window display, draw, clear safe? I can't really put that in a function...
mutex.lock();
window.draw(mySprite);
mutex.unlock();
It was not stupid, it's also a good strategy to assume that everything may throw, and make all your code exception-safe. In this case you can do this:
window.clear();
{
sf::Lock lock(m_mutex);
window.draw(sprite);
}
window.display();