Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Trying to update graphical elements from separate thread  (Read 1423 times)

0 Members and 1 Guest are viewing this topic.

virttop

  • Guest
Trying to update graphical elements from separate thread
« on: August 25, 2017, 12:10:59 am »
Hello everyone, first post here (sorry if this is the wrong place ^^).

I have 10 CircleShapes in a vector and am now trying to update their fill color from a separate thread. It is not working as expected. In fact, nothing happens.
 
When I click the left mouse button I want to iterate over my shape objects, one at a time, and change the background color.

I am using a mutex to lock the objects inside the second thread before modifying them and in the main thread before drawing them.

Help is much appreciated.


#include <SFML/Graphics.hpp>
#include <mutex>
#include <thread>


auto myThreadFunc(std::mutex &mtx, std::vector<sf::CircleShape> &circles) -> void
{
    for (auto &c : circles)
    {
        mtx.lock();
        c.setFillColor(sf::Color::Green);
        mtx.unlock();

        // Animation pace
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(2400, 1200), "SFML works!");
   
    std::mutex mtx;
    std::vector<sf::CircleShape> circles;

    for (auto i = 0; i < 10; i++)
    {
        auto c = sf::CircleShape(100.f);
        c.setFillColor(sf::Color::Cyan);
        c.setPosition(i*200.f, 0);

        circles.push_back(c);
    }

    while (window.isOpen())
    {
        sf::Event e;
        while (window.pollEvent(e))
        {
            if (e.type == sf::Event::Closed)
            {
                window.close();
            }


            if (e.type == e.MouseButtonReleased && e.mouseButton.button == sf::Mouse::Left)
            {
                auto worker = std::thread(myThreadFunc, std::ref(mtx), circles);
                worker.detach();
            }
        }

        window.clear(sf::Color::Black);

        for (auto &circle : circles)
        {
            mtx.lock();
            window.draw(circle);
            mtx.unlock();
        }

        window.display();
    }

    return 0;
}
 



« Last Edit: August 25, 2017, 12:39:16 am by virttop »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11033
    • View Profile
    • development blog
    • Email
Re: Trying to update graphical elements from separate thread
« Reply #1 on: August 25, 2017, 12:21:45 am »
And why do you think you need a separate thread? ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

virttop

  • Guest
Re: Trying to update graphical elements from separate thread
« Reply #2 on: August 25, 2017, 12:29:59 am »
Because I want to do some computations that will cause the GUI to hang and not respond to further events until it has finished :D

virttop

  • Guest
Re: Trying to update graphical elements from separate thread
« Reply #3 on: August 25, 2017, 12:49:31 am »
Fixed it :)

Problem was that std threads requires a reference wrapper when passing arguments by reference between threads.

See this Stackoverflow answer: https://stackoverflow.com/a/34078246


So the solution was to call std::ref() not only on the mutex, but also on the circles vector.

auto worker = std::thread(myThreadFunc, std::ref(mtx), std::ref(circles));
 

 

anything