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

Author Topic: Send a close event to waitEvent  (Read 4007 times)

0 Members and 1 Guest are viewing this topic.

GraphicsWhale

  • Full Member
  • ***
  • Posts: 131
    • View Profile
Send a close event to waitEvent
« on: May 27, 2015, 01:15:35 am »
After many hours of frustration, I found out that trying to close a window from a secondary thread while the primary thread (the window "owner") is waiting for an event will cause the program to abruptly crash due to a segmentation fault caused by SFML. Now I can only mend the issue by polling events every x milliseconds, but it's just not the same.

I'd figure adding the ability to send a close event to a window wouldn't be that difficult. GLFW has something similar that lets me avoid this very problem (an empty event, though, but still gets the attention of the primary thread). I don't know why it's not implemented, but I'd like to see it.

To clarify further, something along the lines of:
window.postCloseEvent();
to cause
sf::RenderWindow::waitEvent
to return a
sf::Event::Closed
when called.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Send a close event to waitEvent
« Reply #1 on: May 27, 2015, 01:44:46 am »
So your actual feature request is to interrupt the blocking sf::Window::waitEvent(), right?

Posting a Closed event is just one possible implementation, and not the best one in my opinion, because it is only useful for your specific use case. It would be better to provide a generic way of interrupting the blocking call and let waitEvent() return false.


Now I can only mend the issue by polling events every x milliseconds, but it's just not the same.
Ironically, it is the same :D

With the current implementation, interrupting the blocking call should not be difficult -- but have you researched a bit what it would mean to a true OS-supported event waiting? Is the interrupt even feasible on all operating systems?
« Last Edit: May 27, 2015, 01:47:09 am by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Send a close event to waitEvent
« Reply #2 on: May 27, 2015, 01:57:47 am »
The crash is caused by concurrent access to the window. If you bother with threading, you need to understand that accessing objects the way you are doing it is dangerous and will almost always lead to undefined behaviour. The fact that you are blocking the main thread in the .waitEvent() call while still being able to call .close() on the window in a secondary thread shows you have no mutual exclusion set up. This was never supposed to work and never will, regardless whether we are talking about SFML objects or other C++ data structures.

If you want to close the window from the second thread, it will have to either do it itself when the first thread is not using the window or just "nicely tell" the first thread to do it. Either way, if you know you are going to have to do this, don't get yourself into the situation of having to unblock a thread from another. There have been numerous questions in the past about how one could cause a thread to resume operation without actually triggering the condition that would make it happen anyway, and the answer is always: don't get yourself into the situation in the first place. There is no well-defined way to do this. Even operating system facilities don't really have a standard way of getting this done.

Luckily for you, SFML provides you with 2 options for polling events, .waitEvent() and .pollEvent(). The former is really just a wrapper around the latter, which you can implement in your own code. If you have to check for a termination condition that the second thread might flag, then do so after .pollEvent() returns and close the window accordingly, it's really as simple as that. Also, if you think that this variant might be slower than .waitEvent(), internally, SFML polls for events and if none are inserted into the event queue, SFML itself sleeps for 10 milliseconds anyway. Saying that having to sleep yourself "is not the same" means that either you are just sleeping too long or are doing something else differently.

There really isn't any reason to use .waitEvent() in SFML, other than saving a few lines of code. Unlike GLFW, it doesn't save CPU time since it doesn't truly cause the process to block in some operating system call. In that sense, having a way to post an empty event to the event queue doesn't make as much sense in SFML as it does in other libraries.

I really wonder if the design of your application is a good one anyway. If you are going to have a second thread constantly running and deciding when the window in the first one is going to close, why even bother using .waitEvent() in the first one in the first place? It doesn't save you anything since the second thread will probably be constantly running anyway.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

GraphicsWhale

  • Full Member
  • ***
  • Posts: 131
    • View Profile
Re: Send a close event to waitEvent
« Reply #3 on: May 27, 2015, 02:35:57 am »
I hesitated to put a mutex in because I didn't want to get it caught with the waitEvent call, and I made the assumption that it was safe enough since I haven't had a crash directly do to that yet (though, I recognized that it was a problem that should eventually be fixed).

Now that I see that waitEvent is actually just a wrapper around pollEvent with a 10ms timer, I'm just going to start using pollEvent (which at least helped me fix the no mutex issues). I'll just use a bool as a quit flag and check it alongside the pollEvent call. So that problem is fixed.

Anyways, back to the original topic, I see why it wasn't implemented given how waitEvent works. But more importantly, why is that function even implemented the way it is? I can't think of any reason why it wouldn't actually do a system call of some sorts. Seems like not only a potential waste of CPU cycles (if no event is triggered), but a small (granted, virtually unnoticeable) delay up to 10ms between when an event is triggered and when the application gets it.

Regardless, I still think it's a feature that should be in there, as it would still be cleaner than making my own system to do just that.

EDIT:
I just re-read Nexus' post.
With the current implementation, interrupting the blocking call should not be difficult -- but have you researched a bit what it would mean to a true OS-supported event waiting? Is the interrupt even feasible on all operating systems?

I'm no expert in writing these kinds of libraries, but it seems to be supported on others.
« Last Edit: May 27, 2015, 02:40:56 am by GraphicsWhale »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Send a close event to waitEvent
« Reply #4 on: May 27, 2015, 03:29:30 am »
Anyways, back to the original topic, I see why it wasn't implemented given how waitEvent works. But more importantly, why is that function even implemented the way it is? I can't think of any reason why it wouldn't actually do a system call of some sorts. Seems like not only a potential waste of CPU cycles (if no event is triggered), but a small (granted, virtually unnoticeable) delay up to 10ms between when an event is triggered and when the application gets it.
Unlike GLFW, SFML returns events directly from the poll/wait functions which is also how SDL does things ("inspiration" ::)). Also, unlike GLFW, both SFML and SDL support joystick events, alleviating the user of having to constantly poll the joysticks themselves.

Because joystick events are not generated by the windowing subsystem, performing an operating system block in a .waitEvent() call would prevent/delay joystick events from being generated by the libraries if the call were to block for a substantial amount of time. This would severely cripple joystick support, and is the main reason why both SFML and SDL have to rely on constantly polling/sleeping.

It's simply a consequence of how the libraries were designed.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).