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

Author Topic: Render and event loop in different threads?  (Read 9683 times)

0 Members and 2 Guests are viewing this topic.

jpileborg

  • Newbie
  • *
  • Posts: 2
    • View Profile
Render and event loop in different threads?
« on: January 12, 2014, 08:36:19 am »
I'm trying to use SFML 2.1 for a small simple project, and want to have the renderer and the event loop in different threads. However it doesn't seem to be possible, as the program either crashes (segmentation fault) or get some X11 error:

XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
      after 106 requests (106 known processed) with 0 events remaining.
 

My test program is about the simplest possible:

#include <iostream>
#include <thread>
#include <SFML/Window.hpp>

namespace
{
    void renderer(sf::Window& window)
    {
        window.setActive(true);
        while (window.isOpen())
        {
            window.display();
        }
    }
}

int main()
{
    sf::Window window(sf::VideoMode(1280, 800), "Testing",
        sf::Style::Default, sf::ContextSettings(32));

    window.setActive(false);
    std::thread render_thread{renderer, std::ref(window)};

    while (window.isOpen())
    {
        sf::Event event;
        while (window.isOpen() && window.pollEvent(event))
        {
        }
    }

    render_thread.join();
}
 

Is there a way to run the rendering and event loop from different threads using SFML 2? I tried a similarly simple program using SDL2 and it works okay.

AlexAUT

  • Sr. Member
  • ****
  • Posts: 396
    • View Profile
Re: Render and event loop in different threads?
« Reply #1 on: January 12, 2014, 01:39:39 pm »
I'm not quite sure but I think I have read that you have to do the rendering in the thread you created the context(renderwindow). So try to do the eventhandling in the other thread.

I'm not at home so I can't test it.


AlexAUT
« Last Edit: January 13, 2014, 04:52:10 pm by AlexAUT »

jpileborg

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Render and event loop in different threads?
« Reply #2 on: January 12, 2014, 02:24:58 pm »
I'm not quite sure but I think I have read that you have to do the rendering in the thread you created the context(renderwindow). So try to do the eventhandling in the other thread.

I tried that, and the program aborted as soon as it received an event. However the error message gave me a hint, saying that I probably had forgotten to call XInitThreads first.

After I did that, it worked fine. Both creating the window in the "main" thread and then doing the rendering in a separate thread with event handling in the main thread, and doing the opposite (window creation and rendering in the main thread, while doing event handling in a new thread).

So if anyone wants to handle event-loop and rendering in different threads, remember to call XInitThreads before opening the window (I have it as the first call in the main function).
« Last Edit: January 12, 2014, 02:26:32 pm by jpileborg »

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Re: Render and event loop in different threads?
« Reply #3 on: January 13, 2014, 12:07:55 pm »
TL; DR: Don't do it; Can of worms!

The longer explanation:

Event handling has to happen in the thread that created the window. Otherwise you might run into weird things happening (as you noticed). There are workarounds, that will make it work (e.g. XInitThreads), but as far as I know all this does is essentially adding some locks to avoid both threads modifying values at the same time (i.e. making it thread safe). But keep in mind that this adds overhead and might slow down everything more than what you gain due to parallelization. In the end you'll no longer hae to process events in your main loop, but instead you'll have to wait for the event thread. Not to forget that it's not a cross platform solution and requires some more code (and if you're unlucky it's really hard to debug these issues!).

Also consider that most event handling is really trivial to do and is partially multithreaded by the operating system/window manager already). If you really think you'll need multithreading, then do it differently:

Keep event handling and drawing in the thread where you also created your window. This will avoid most awkward situations and problems. Then just move game logic to a second thread and you should be fine. All you'll have to do is use a *sf::Mutex* together with *sf::Lock* in both threads.

Fizix

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: Render and event loop in different threads?
« Reply #4 on: January 13, 2014, 03:54:42 pm »
Don't try to poll the events on another thread.  Poll events on the main thread and once an event is available, add it to your own queue (std::queue<sf::Event>?), which gets processed in a loop on a different thread.

Synchronizing the two threads can not be avoided and you'll end up with the main thread having to wait for the event thread and vice versa, which is worse than just doing both on the main thread in the first place.

You might want to look into task based parallelism.