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

Author Topic: Linux Threading Issue  (Read 27845 times)

0 Members and 1 Guest are viewing this topic.

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« on: December 03, 2011, 12:44:40 pm »
Just grabbed some code I've been working on from my Windows machine and loaded it onto Linux and it isn't working. The error message suggests that it is on SFML's end, not mine, though when I tried the minimal threading example from the tutorials, it worked fine.

The error message is:

Code: [Select]
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
ElectroToy: ../../src/xcb_io.c:273: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Aborted

Process returned 134 (0x86)   execution time : 0.232 s
Press ENTER to continue.


My code (I haven't worked on it for long yet so don't judge :p)

Code: [Select]
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>

#define WIDTH 800
#define HEIGHT 600

sf::RenderWindow App();
sf::Uint8 *pixels = new sf::Uint8[WIDTH * HEIGHT * 4];

void draw(int x, int y, int r, int g, int b)
{
    pixels[(x + WIDTH * y) * 4 + 0] = r;
    pixels[(x + WIDTH * y) * 4 + 1] = g;
    pixels[(x + WIDTH * y) * 4 + 2] = b;
    pixels[(x + WIDTH * y) * 4 + 3] = 255;
}

void display(void *UserData)
{
    sf::RenderWindow App(sf::VideoMode(WIDTH, HEIGHT, 32), "Speed Test");
    sf::Image screen(WIDTH, HEIGHT);
    sf::Sprite sprite;
    while (1)
    {
        screen.LoadFromPixels(WIDTH, HEIGHT, pixels);
        sprite.SetImage(screen);
        App.Clear();
        App.Draw(sprite);
        App.Display();
    }
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(WIDTH, HEIGHT, 32), "Speed Test");
    sf::Thread graphics(&display);
    sf::Clock clock;
    const sf::Input & Input = App.GetInput();
    bool mouseX = Input.GetMouseX();
    bool mouseY = Input.GetMouseY();
    bool leftMouse = Input.IsMouseButtonDown(sf::Mouse::Left);
    bool rightMouse = Input.IsMouseButtonDown(sf::Mouse::Right);
    graphics.Launch();
    while (1)
    {
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }
        if (leftMouse)
            draw(mouseX, mouseY, 255, 255, 255);
    }
}
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Linux Threading Issue
« Reply #1 on: December 03, 2011, 02:15:40 pm »
Are you aware that:
- you have one RenderWindow in your main() function
- you have another RenderWindow in your display() function
- sf::RenderWindow App() declares a function and has nothing to do with the two other App variables?

What you want is a single RenderWindow instance, shared by the main and secondary threads, right?
Laurent Gomila - SFML developer

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #2 on: December 08, 2011, 05:02:44 am »
Yes, that is exactly what I was trying to do but I couldn't get it working.

Could someone please help me with this?
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

nitrix

  • Newbie
  • *
  • Posts: 27
    • View Profile
Linux Threading Issue
« Reply #3 on: December 08, 2011, 05:31:05 am »
I'd personally use a Singleton, but it's arguable what is best.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Linux Threading Issue
« Reply #4 on: December 08, 2011, 08:12:08 am »
Don't declare a global RenderWindow.
Declare a RenderWindow local to the main() function.
Pass a pointer to it to your thread function.

That's it ;)
Laurent Gomila - SFML developer

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #5 on: December 08, 2011, 10:27:07 am »
Oh of course...didn't think of that. Thanks a bunch
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #6 on: December 10, 2011, 10:24:12 am »
Okay, I've been trying to get this working but it...well...isn't. I've got rid of most of it because it is irrelevant to my problem though I am still working on what I posted above just so you know. The code below compiles and runs on windows with MSVC++ though says something like could not create OpenGL context for this device. On Linux with Code blocks and GCC though it won't compile at all as it is complaining about conversion from int* to sf::WindowHandle. Keep in mind, my code isn't debugged because I can't, so if you pick anything up, feel free to fix it :)

Code: [Select]
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

#define WIDTH 800
#define HEIGHT 600

void display(void *UserData)
{
sf::RenderWindow App = (int*)UserData;
    sf::Image screen(WIDTH, HEIGHT);
    sf::Sprite sprite;
    while (1)
    {
        App.Clear();
        App.Draw(sprite);
    }
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(WIDTH, HEIGHT, 32), "ElectroToy");
    sf::Thread graphics(&display, &App);
    graphics.Launch();
    while (1)
    {
App.Display();
    }
}
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Linux Threading Issue
« Reply #7 on: December 10, 2011, 10:34:05 am »
Quote
sf::RenderWindow App = (int*)UserData;

Here you're declaring a new RenderWindow instance, trying to construct it with a pointer to a RenderWindow interpreted as a pointer to int. Doesn't make sense at all :)

Here is the correct code:
Code: [Select]
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

#define WIDTH 800
#define HEIGHT 600

void display(void *UserData)
{
   sf::RenderWindow* App = static_cast<sf::RenderWindow*>(UserData);
    sf::Image screen(WIDTH, HEIGHT);
    sf::Sprite sprite;
    while (1)
    {
        App->Clear();
        App->Draw(sprite);
    }
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(WIDTH, HEIGHT, 32), "ElectroToy");
    sf::Thread graphics(&display, &App);
    graphics.Launch();
    while (1)
    {
      App.Display();
    }
}


But your code won't work as expected. Why are you using a thread?
Laurent Gomila - SFML developer

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #8 on: December 10, 2011, 10:59:39 am »
Firstly, I am using a thread because I plan to have the main bit of the game running in one thread, and having another one doing nothing but drawing because the drawing things to bitmaps then displaying them isn't very fast and I would rather it didn't slow the whole thing down.

Ok, so I have put the fix into the code though for reasons I cannot understand, on linux it complains about the threading with the error I posted in first post. On Windows it just doesn't display the window unless I put the function call in the main thread.

Code: [Select]

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>

#define WIDTH 800
#define HEIGHT 600

sf::Uint8 *pixels = new sf::Uint8[WIDTH * HEIGHT * 4];

void draw(int x, int y, int r, int g, int b)
{
    pixels[(x + WIDTH * y) * 4 + 0] = r;
    pixels[(x + WIDTH * y) * 4 + 1] = g;
    pixels[(x + WIDTH * y) * 4 + 2] = b;
    pixels[(x + WIDTH * y) * 4 + 3] = 255;
}

void display(void *UserData)
{
    sf::RenderWindow* App = static_cast<sf::RenderWindow*>(UserData);
    sf::Image screen(WIDTH, HEIGHT);
    sf::Sprite sprite;
    while (1)
    {
        screen.LoadFromPixels(WIDTH, HEIGHT, pixels);
        sprite.SetImage(screen);
        App->Clear();
        App->Draw(sprite);
        App->Display();
    }
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(WIDTH, HEIGHT, 32), "ElectroToy");
    sf::Thread graphics(&display, &App);
    sf::Clock clock;
    const sf::Input & Input = App.GetInput();
    bool mouseX = Input.GetMouseX();
    bool mouseY = Input.GetMouseY();
    bool leftMouse = Input.IsMouseButtonDown(sf::Mouse::Left);
    bool rightMouse = Input.IsMouseButtonDown(sf::Mouse::Right);
    graphics.Launch();
    while (1)
    {
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }
        if (leftMouse)
            draw(mouseX, mouseY, 255, 255, 255);
    }
}
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Linux Threading Issue
« Reply #9 on: December 10, 2011, 11:01:43 am »
You must call App.SetActive(false) before launching the graphics thread.

And you should protect your pixel data with a mutex.
Laurent Gomila - SFML developer

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #10 on: December 10, 2011, 11:10:42 am »
That fixed the problem on Windows with MSVC++ though Linux with Code::Blocks is still giving the threading error.

Also, what is the advantage of using a mutex as display() only ever reads and main() only ever writes?
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Linux Threading Issue
« Reply #11 on: December 10, 2011, 11:34:06 am »
Quote
Linux with Code::Blocks is still giving the threading error

Which one?

Quote
Also, what is the advantage of using a mutex as display() only ever reads and main() only ever writes?

The effects of concurrent access will probably be limited in your case, but it can still happen. You could update a pixel in the middle of its upload to the graphics card; even a single read/write operation can be interrupted since not all platforms ensure that these operations are atomic.
Laurent Gomila - SFML developer

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #12 on: December 10, 2011, 11:42:30 am »
Quote
The effects of concurrent access will probably be limited in your case, but it can still happen. You could update a pixel in the middle of its upload to the graphics card; even a single read/write operation can be interrupted since not all platforms ensure that these operations are atomic.

Ok, I'll add it once I have this working.

As for which Linux Distro; Debian (Unstable) KDE
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Linux Threading Issue
« Reply #13 on: December 10, 2011, 12:06:26 pm »
Quote
As for which Linux Distro; Debian (Unstable) KDE

My question was "which error", not "which Linux", sorry.
Laurent Gomila - SFML developer

Jalfor

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Linux Threading Issue
« Reply #14 on: December 10, 2011, 12:31:50 pm »
Ah, this one:

Code: [Select]

[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.
ElectroToy: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted

Process returned 134 (0x86)   execution time : 0.211 s
Press ENTER to continue.
If a picture tells 1000 words, then a YouTube video clearly tells 1000000 making a YouTube video obviously a larger work than the Lord Of The Rings, or some other massive novel. Thus are the laws of YouTube videos.