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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Pablo

Pages: [1]
1
Patch available: could you head over https://github.com/SFML/SFML/pull/962 and give it a try? Thanks

I have just checked it out and it works like a charm in both release and debug versions. Thanks a million for the hard work, Hiura  ;)

2
Looks indeed like an issue in the OS X implementation. Time to wait for Hirua's comment. ;)

Two points about your code:
* bool is not an atomic type and operations on it require synchronization as well, or you use the C++11 atomic symbols.
* Keep in mind that std::hash's hashing algorithm is compiler/toolchain specific and it's not always very good.

Thanks for the feedback, I didn't know about the hash being compiler/toolchain specific. I just used that because I googled how to print the current thread id and I thought it was the proper way of doing it in C++11. Anyway, I just wanted to print unambiguously each thread.

I kept the exitThreadFlag simple for the sake of the minimal example. Although the behavior of reading/writing concurrently the same bool is not defined, as far as I understand, for this example in the worst case you'd be running 1 extra iteration within the loop, which doesn't seem to be a ver big problem in this case. But yes, in case you're doing more complicated things and even if you're not a purist coder, you'd better protect every shareable zone with something to avoid race conditions.

Quote
Hey Hey, thanks for the *proper* bug report. It's not everyday I get something that clear about a bug. So let's focus on the issue at hand and not digress on opinion based topic about MT programming, shall we? :-)

BTW, to debug things, use your debugger, it's way faster since you don't need to edit code to add prints. In this case, I added breakpoints in releasePool() and retainPool() that automatically continue executing code after executing bt -c 0 (print only the header of the backtrace) and I get the following:

You're welcome. Thanks for the advice and for working to figure out the workaround :D. The thing is that I didn't have the SFML project loaded into my IDE  (so that I can debug with it, as I have no idea of using gdb manually) and wasn't setting correctly the breakpoints. Also, I come from the embedded software world where most of the times you cannot really debug in real-time, so I'm used to prepare some logs the moment I have any issue debugging. In any case, you're right, it's way faster to use the debug, because it also provides you with tons of information quite complex to gather of any other way. I'd rather had invested some time importing the project into my IDE, though  8)

BTW, the sf::Shader::isAvailable() trick works like a charm, thanks a million.

3
Regarding your question. If you read the documentation I believe you'll find that it clearly states that events must be processed in the Window's thread and I'm fairly certain that drawing must also happen in the main thread of the executable (although I can't find the documentation to back that up right now).

Yes, indeed in the example I'm processing all the events in the main thread (which is the one that created the window). If you had to do all the drawing in the main thread then there'd be no point in creating a rendering thread at all. But as there's a tutorial for doing it so, it should mean it's possible.

4
I agree 100% with you, Jesper. What I meant in my previous post is that multithreading is a difficult thing "per se", not because of the fact that C++ makes it much more difficult than other languages.

Having said that, my goal opening this post was not to start a war about multithreading, but about helping to identify what might be a bug.

5
General / Re: The Beginning of an MMO
« on: January 28, 2015, 01:02:15 am »
Valve wrote some very good documents explaining how they handle networking in their engine. Have a look at them. They're quite interesting:

https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization


6
Unfortunately I do not know how to synchronize threads. Multithreading in C++ increases code complexity by about a billion percent and you cannot tackle it head on like single threaded applications. It requires a completely different mindset.

Multithreading in C++ has become a lot easier with C++11. I guess you're more used to Java, but using sf::Mutex or std::mutex and lockers is not that difficult. The difficult part comes when you have to deal with race conditions, etc, but that's not something C++ related but multithreaded related.

I agree with both of you that multithreading complicates the code. I do. But there's an example in the tutorials explaining how you may use it. It should work, right? I'm not saying I'm going to use multithreading rendering, but I was just writing a PoC of how it would be and found what I think might be a bug (because it seems different OSs handle windows quite different) and wanted to report it here to know whether I'm missing something or is some issue.

7
You need to synchronize the threads so that they know what is happening. Without it, ... Well you can guess.

(click to show/hide)

Thanks for the quick response. What kind of synchronization you are refering to? I took the example from the tutorials, and I tested that worked on Windows. One thing that I added is that instead of directly closing the window from the main thread, I change a flag and wait for the rendering thread to finish cleanly. I'd call that synchronization. Not an elegant way of synchronization, but synchronization after all. Anyway, if you're able to reproduce the issue and fix it synchronizing both threads, I'd like to know how.

Cheers


8
Hi,

I've been trying to run my game engine doing all the rendering in a different thread following the tutorial http://www.sfml-dev.org/tutorials/2.2/graphics-draw.php#drawing-from-threads

I've also read http://www.sfml-dev.org/tutorials/2.2/window-window.php#things-to-know-about-windows and if I understood correctly, in Mac there are these two main constraints:

  • Events must be polled in the window's thread
  • On OS X, windows and events must be managed in the main thread --> Mac OS X just won't agree if you try to create a window or handle events in a thread other than the main one.

I get I can't neither poll the events nor create the window in a different thread than the main one. What is happening to me, though, is that the moment I render something, on destruction of the window I have the following crash:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Application Specific Information:
Assertion failed: (localPool != NULL), function releasePool, file /Users/pablo/Game/ThirdParty/SFML/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm, line 203.
 

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib              0x00007fff833f5282 __pthread_kill + 10
1   libsystem_c.dylib                   0x00007fff8d081b73 abort + 129
2   libsystem_c.dylib                   0x00007fff8d049c59 __assert_rtn + 321
3   libsfml-window-d.2.2.0.dylib        0x000000010c231f81 releasePool() + 305
4   libsfml-window-d.2.2.0.dylib        0x000000010c2285d2 sf::priv::SFContext::~SFContext() + 146
5   libsfml-window-d.2.2.0.dylib        0x000000010c228635 sf::priv::SFContext::~SFContext() + 21
6   libsfml-window-d.2.2.0.dylib        0x000000010c228658 sf::priv::SFContext::~SFContext() + 24
7   libsfml-window-d.2.2.0.dylib        0x000000010c206e95 sf::priv::GlContext::globalCleanup() + 693
8   libsfml-window-d.2.2.0.dylib        0x000000010c20ad66 sf::GlResource::~GlResource() + 70
9   libsfml-window-d.2.2.0.dylib        0x000000010c211ba3 sf::Window::~Window() + 51
10  libsfml-graphics-d.2.2.0.dylib      0x000000010c289aed sf::RenderWindow::~RenderWindow() + 45
11  libsfml-graphics-d.2.2.0.dylib      0x000000010c289b45 sf::RenderWindow::~RenderWindow() + 21
12  Game                                0x000000010c18de47 main + 679
13  libdyld.dylib                       0x00007fff87f7e5c9 start + 1
 

This is a minimal example to reproduce the issue:

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

bool exitThread = false;

void renderingThread(sf::RenderWindow* window)
{
    printf("Rendering thread %lu started\n", std::hash<std::thread::id>()(std::this_thread::get_id()));
    sf::CircleShape shape(50);
    shape.setFillColor(sf::Color(150, 50, 250));

    // set a 10-pixel wide orange outline
    shape.setOutlineThickness(10);
    shape.setOutlineColor(sf::Color(250, 150, 100));

    // the rendering loop
    while (!exitThread && window->isOpen())
    {
        // draw...
        window->draw(shape); // if I comment this line, it works

        // end the current frame
        window->display();
    }
}

int main(int argc, char* argv[]) {
    printf("Main thread %lu started\n", std::hash<std::thread::id>()(std::this_thread::get_id()));

    //create the window (remember: it's safer to create it in the main thread due to OS limitations)
    sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL");

    // deactivate its OpenGL context
    window.setActive(false);

    // launch the rendering thread
    sf::Thread thread(&renderingThread, &window);
    thread.launch();

    // the event/logic/whatever loop
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed || (event.key.code == sf::Keyboard::Escape)) {
                printf("Closing\n");

                // closing the window when renderingThread still uses it causes lots of
                // GL_INVALID_FRAMEBUFFER_OPERATION, the object bound to FRAMEBUFFER_BINDING is not "framebuffer complete"
                //window.close();

                exitThread = true;
                thread.wait();
                window.close();
            }
        }
    }

    return 0;
}
 

If I don't draw anything, it doesn't crash. I changed slightly the AutoreleasePoolWrapper, SFContext and WindowImplCocoa to check what it was retaining and releasing from which thread adding a few log traces:

This is the output of the code provided at the end in debug:

Main thread 4217047789276772314 started
SFContext::SFContext 0x7fa603c1db30 retainPool from thread 4217047789276772314
AutoreleasePoolWrapper::retainPool: entered for 1 time from thread 4217047789276772314
AutoreleasePoolWrapper::retainPool: creating new pool from thread 4217047789276772314
SFContext::SFContext 0x7fa603e0a440 retainPool from thread 4217047789276772314
AutoreleasePoolWrapper::retainPool: entered for 2 time from thread 4217047789276772314
WindowImplCocoa::VideoMode 0x7fa603e0c230 retainPool from thread 4217047789276772314
AutoreleasePoolWrapper::retainPool: entered for 3 time from thread 4217047789276772314
SFContext::SFContext,WindowImpl 0x7fa603d0c680 retainPool from thread 4217047789276772314
AutoreleasePoolWrapper::retainPool: entered for 4 time from thread 4217047789276772314


Rendering thread 13536384218981027915 started
SFContext::SFContext 0x7fa6058649d0 retainPool from thread 13536384218981027915
AutoreleasePoolWrapper::retainPool: entered for 5 time from thread 13536384218981027915
AutoreleasePoolWrapper::retainPool: creating new pool from thread 13536384218981027915
SFContext::~SFContext 0x7fa6058649d0 releasePool from thread 13536384218981027915
AutoreleasePoolWrapper::releasePool: entered for 1 time from thread 13536384218981027915
AutoreleasePoolWrapper::releasePool: releasing pool for thread 13536384218981027915
SFContext::SFContext 0x7fa605859e80 retainPool from thread 13536384218981027915
AutoreleasePoolWrapper::retainPool: entered for 6 time from thread 13536384218981027915
AutoreleasePoolWrapper::retainPool: creating new pool from thread 13536384218981027915
Closing


SFContext::~SFContext 0x7fa603d0c680 releasePool from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: entered for 2 time from thread 4217047789276772314
WindowImplCocoa::~WindowImplCocoa 0x7fa603e0c230 releasePool from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: entered for 3 time from thread 4217047789276772314
SFContext::~SFContext 0x7fa603c1db30 releasePool from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: entered for 4 time from thread 4217047789276772314
SFContext::~SFContext 0x7fa603e0a440 releasePool from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: entered for 5 time from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: releasing pool for thread 4217047789276772314
SFContext::~SFContext 0x7fa605859e80 releasePool from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: entered for 6 time from thread 4217047789276772314
AutoreleasePoolWrapper::releasePool: has NULL localPool for thread 4217047789276772314. assert expected

Assertion failed: (localPool != NULL), function releasePool, file /Users/pablo/Game/ThirdParty/SFML/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm, line 208.
Abort trap: 6

It seems pretty clear that since AutoreleasePoolWrapper is using localPool as a TLS variable, and the SFContext from the rendering thread is called from that thread whereas its deconstructor is called from the main one. When this happens, localPool from the main thread has already been released. The question I guess is whether I'm doing something wrong or this is the usual behavior and I'm missing something in here. Please feel free to give any feedback cause I've already tried tons of things.

Something as simple as adding a checking would "solve" the crash, but it doesn't solve the deep issue which is that the constructor is called from one thread whereas the desctructor is called from another one, making that the pool of "the other thread" (aka. rendering thread) is never released.

void releasePool(void)
{
    if (localPool == NULL) {
        return;
    }
    ...
 

My OS is Yosemite 10.10.1 and I'm using SFML 2.2 compiled by myself.

Sorry for the long post but I wanted to provide as much information as possible to help figuring out the problem. Also, I'm not sure if this is the proper place for this post or Help->Window is better. Please feel free to move it.

Thanks a million in advance  :D

Pages: [1]
anything