Destroying multiple windows individually


#1

Hello! today I was working on my python opengl library, and I switched to GLFW because of it’s promising simplicity and quality.
Right now a single window works fine, but I have a problem with destroying windows when there is more than one. Each window’s loop is running in a separate thread, because i dont want to call makeContextCurrent each frame, so we’ve got 2 threads.
The loops are identical, each executing this order:
render() -> swapBuffers(window) -> pollEvents()

Each window’s main loop code:

Code

while not glfw.window_should_close(self.window){ render() glfw.swap_buffers(self.window) glfw.poll_events() } glfw.destroy_window(self.window) print("destroyed")

Now to the voodoo part:
When i press exit on my main thread’s window it closes, and the other window stops reacting to events, forcing me to terminate the process.
when i press exit in my second window, it calls the destroy function (“destroyed” is printed) but nothing happens! and then if i press it again, the window closes properly.

A: What could be the possible explanation for having to click exit twice?
B: Why pollEvents is not window specific? polling from both threads doesnt seem to be the problem because i tested it both ways, and the results were the same. Maybe i don’t understand something about the event system which makes me voodoofied?

I’d be eternally grateful if someone helps me out with this :slight_smile:
I simply want to make an independant black window class


#2

As per the documentation on glfwPollEvents this function should only be called on the main application thread. You can continue to do all rendering on the separate window threads. For a little more explication see the answer by @elmindreda on this thread.

So try this approach of a single poll function in the main thread, and if you continue to have issues let us know.


#3

Thanks for the tip, I missed that part in the docs.
Anyway, I did try calling pollEvents only from the main thread. It did not change anything, but as a good practice i’m gonna keep doing that. I still get that problem when I destroy my separate thread window, and it closes only after I press exit the second time (after it has already been destroyed)


#4

This is a fairly complicated problem and without access to the entire source code it’s difficult to help you debug your problem, but here’s some thoughts:

You need to keep polling events until you decided to close ALL windows. One architecture to achieve this would be to poll events on the main thread, and then render each window on separate threads. Note that window creation and destruction need to be called from the main thread, then you can pass the window handles to your render threads. The C function glfwWindowShouldClose can be called from any thread, and I guess that this is also true for the python glfw.window_should_close() function. Note that with this approach you may want to change the event handling call from poll_events() to glfwWaitEvents otherwise your main loop may spin using up CPU cycles needlessly.

Polling events is not window specific for OS specific reasons, and because many events are not window specific themselves. However the events themselves can be window specific, and glfw passes the window handle to any callback you’ve set so that you can take the relevant action.


#5

Up until now I’ve been destroying each window in it’s respective thread, and looking at your answer I’m now testing the other way of managing all the events at the main thread. And then I can feed the events into a message queue for each window.to read.
Trying it now, It worked! :slight_smile:
Thank you greatly.
Do you know if there’s any difference between running my window in the main thread vs sub-thread, like I do now? like, at the window level.


#6

Excellent, glad that works.

It’s a common pattern to have a main thread processing events, and a thread per window to handle rendering - so if this is what you’re now doing that sounds like the correct approach to continue with for OpenGL.