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

Author Topic: sf::Keyboard::isKeyPressed causes failure when multithreaded?  (Read 1893 times)

0 Members and 1 Guest are viewing this topic.

soccermiles

  • Newbie
  • *
  • Posts: 2
    • View Profile
I'm using Ubuntu 12.04 and SFML 2.0.

Whenever I try to separate my message processing from my graphics, bad things seem to happen. In this instance, I'm trying to take input in one thread, and draw to the window in another. This works fine as long as I only use the event loop. But I don't want to have my own input accumulator, so I figured I'd use sf::Keyboard::isKeyPressed for some of my input handling. But when I uncomment the lines containing sf::Keyboard::isKeyPressed, shown in my main below, something strange happens. Assuming I recompiled it from scratch, I'm able to run the program just fine, once, but it prints the following error to STDERR when I close it...

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
ebola: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted (core dumped)


If I run it a second time without recompiling, the window flashes in and out of existence, and that error is printed to the terminal again. The weird thing is that the first time, the window operated exactly as expected, until I closed it myself. The second time, it closed itself before anything could be done about it.

The following program reproduces the problem on Ubuntu 12.04 64-bit...
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

static void init();
static void gloop();
static void lloop();
static void stop();

static sf::RenderWindow* window;
static sf::CircleShape shape(300.f);
static sf::Thread* thread;
static sf::Mutex mutex;
static sf::Color color;

int main()
{
    init();
    gloop();
    stop();
}

static void init()
{
    //initialize generic resources, get thread going
    window = new sf::RenderWindow(sf::VideoMode(600, 600), "SFML works!");
    color.r = 0;
    color.g = 0;
    color.b = 0;
    color.a = 255;
    shape = sf::CircleShape(300.f);
    shape.setFillColor(color);
    thread = new sf::Thread(&lloop);
    thread->launch();
}

static void gloop()
{
    while(window->isOpen())
    {
        window->clear();

        mutex.lock();
        window->draw(shape);
        mutex.unlock();

        window->display();
    }
}

static void stop()
{
    thread->wait();
}

static void adjust(int r, int g, int b)
{
    color.r = (color.r + r) & 255;
    color.g = (color.g + g) & 255;
    color.b = (color.b + b) & 255;
    shape.setFillColor(color);
}

static void lloop()
{
    while(window->isOpen())
    {
        sf::Event event;
        while(window->pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                    window->close();
                    break;

                default:
                    break;
            }
        }

        //if(sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) adjust(1, 0, 0);
        //if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) adjust(-1, 0, 0);
        //if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) adjust(0, 1, 0);
        //if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)) adjust(0, -1, 0);
        //if(sf::Keyboard::isKeyPressed(sf::Keyboard::E)) adjust(0, 0, 1);
        //if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)) adjust(0, 0, -1);

        mutex.lock();
        shape.setFillColor(color);
        mutex.unlock();
    }
}
« Last Edit: May 28, 2013, 10:39:11 pm by soccermiles »

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 878
    • View Profile
Re: sf::Keyboard::isKeyPressed causes failure when multithreaded?
« Reply #1 on: June 10, 2013, 10:28:03 am »
Haven't tried that code yet, but it's in general a very bad idea to "split" one window over multiple threads.

Don't create your window in your main thread and then try to poll events in another thread (or vice versa). If you really want to split graphics rendering and game logic using threads, put the graphics loop (and event handling) in your main thread and do the logic handling in a separate thread.

soccermiles

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: sf::Keyboard::isKeyPressed causes failure when multithreaded?
« Reply #2 on: June 10, 2013, 05:41:19 pm »
I guess that sounds reasonable, but I'd like to know: Why's it such a bad idea? It makes sense not to try to access OpenGL from multiple threads when there's just one context, but the whole window?