if I have a mainthread that sets up a GLUT window and then create a working thread to do calculations and during the calculations upon some events in the working thread i want to update my GLUT window. How can I do that?
Apparently I can't call the glut functions directly from the working thread.
I thoght of setting some 'updateflag' that gets checked in the glut Idle Loop and if it's set then to redraw the GLUT window, but aparently it doesn't work to call glut functions from the idle loop either (or at least shouldn't be done).
So - what's the proper way to do that?
thanks!
That's a common problem with most GUI frameworks (most are normally not threadsafe).
The normal solution is posting invocations to the main event loop. I am not sure what thread library you use (some will probably have the concept of delegates etc), but in your case a simple event queue would probably do it.
And yes, you can redraw the window from the idle function. At least I've always done it...
well I've implemented multi-thread on GLUT for calculations what I do it's ad a bool flag that tells the glut once an event has happened on the other thread, then I have a stack with data collected on the other thread and just reuse the stack on the main GLUT thread, on that way I manage to keep glut working but not stopping the rendering.
I use Async <- for multithread functions
Related
The SDL documentation for threading states:
NOTE: You should not expect to be able to create a window, render, or receive events on any thread other than the main one.
The glfw documentation for glfwCreateWindow states:
Thread safety: This function must only be called from the main thread.
I have read about issues regarding the glut library from people who have tried to run the windowing functions on a second thread.
I could go on with these examples, but I think you get the point I'm trying to make. A lot of cross-platform libraries don't allow you to create a window on a background thread.
Now, two of the libraries I mentioned are designed with OpenGL in mind, and I get that OpenGL is not designed for multithreading and you shouldn't do rendering on multiple threads. That's fine. The thing that I don't understand is why the rendering thread (the single thread that does all the rendering) has to be the main one of the application.
As far as I know, neither Windows nor Linux nor MacOS impose any restrictions on which threads can create windows. I do know that windows have affinity to the thread that creates them (only that thread can receive input for them, etc.); but still that thread does not need to be the main one.
So, I have three questions:
Why do these libraries impose such restrictions? Is it because there is some obscure operating system that mandates that all windows be created on the main thread, and so all operating systems have to pay the price? (Or did I get it wrong?)
Why do we have this imposition that you should not do UI on a background thread? What do threads have to do with windowing, anyways? Is it not a bad abstraction to tie your logic to a specific thread?
If this is what we have and can't get rid of it, how do I overcome this limitation? Do I make a ThreadManager class and yield the main thread to it so it can schedule what needs to be done in the main thread and what can be done in a background thread?
It would be amazing if someone could shed some light on this topic. All the advice I see thrown around is to just do input and UI both on the main thread. But that's just an arbitrary restriction if there isn't a technical reason why it isn't possible to do otherwise.
PS: Please note that I am looking for a cross platform solution. If it can't be found, I'll stick to doing UI on the main thread.
While I'm not quite up to date on the latest releases of MacOS/iOS, as of 2020 Apple UIKit and AppKit were not thread safe. Only one thread can safely change UI objects, and unless you go to a lot of trouble that's going to be the main thread. Even if you do go to all the trouble of closing the window manager connection etc etc you're still going to end up with one thread only doing UI. So the limitation still applies on at least one major system.
While it's possibly unsafe to directly modify the contents of a window from any other thread, you can do software rendering to an offscreen bitmap image from any thread you like, taking as long as you like. Then hand the finished image over to the main thread for rendering. (The possibly is why cross platform toolkits disallow/tell you not to. Sometimes it might work, but you can't say why, or even that it will keep working.)
With Vulkan and DirectX 12 (and I think but am not sure Metal) you can render from multiple threads. Woohoo! Of course now you have to figure out how to do all the coordination and locking and cross-synching without making the whole thing slower than single threaded, but at least you have the option to try.
Adding to the excellent answer by Matt, with Qt programs you can use invokeMethod and postEvent to have background threads update the UI safely.
It's highly unlikely that any of these frameworks actually care about which thread is the 'main thread', i.e., the one that called the entry point to your code. The real restriction is that you have to do all your UI work on the thread that initialized the framework, i.e., the one that called SDL_Init in your case. You will usually do this in your main thread. Why not?
Multithreaded code is difficult to write and difficult to understand, and in UI work, introducing multithreading makes it difficult to reason about when things happen. A UI is a very stateful thing, and when you're writing UI code, you usually need to have a very good idea about what has happened already and what will happen next -- those things are often undefined when multithreading is involved. Also, users are slow, so multithreading the UI is not really necessary for performance in normal cases. Because of all this, making a UI framework thread-safe isn't usually considered beneficial. (multithreading compute-intensive parts of your rendering pipeline is a different thing)
Single-threaded UI frameworks have a dispatcher of some sort that you can use to enqueue activities that should happen on the main thread when it next has time. In SDL, you use SDL_PushEvent for this. You can call that from any thread.
I have a call to an external program that opens a "modal" window, since it's in the same thread as the main loop it blocks redrawing of the underlying window.
The program runs as a separate process and I am communicating with the program via pipes.
From what I've read it's bad practice to have an additional main loop, so what is the correct way to avoid this lockup?
The question is how to make a separate thread in my own program to do the communication with that program without blocking the entire main loop.
Use a non blocking API to run the external program, such as GSubprocess https://developer.gnome.org/gio/stable/GSubprocess.html or the lower level spawn API https://developer.gnome.org/glib/stable/glib-Spawning-Processes.html
You could also use a thread but the above APIs are much easier.
You have to somehow return control to the main loop while the subprocess runs, that's the bottom line.
I'm porting an ancient VB6 program to C#/.Net. I don't know VB6 very well and I'm asking this to understand it better.
The old VB6 program had a main course of program execution, but it also had lots of event handlers either for socket events or for timer events and the handlers for these often manipulated shared resources, e.g., common global variables, whenever they woke up and ran.
Nonetheless the old program seemed to run OK.
Trying to do this same architecture in C# is disastrous because event handlers for the socket or timers are called by the system in different threads from the main application thread and result in frequent exceptions like "The calling thread cannot access this object because a different thread owns it.", not to mention more subtle problems. Most of my work in the conversion is re-architecting the program to make it thread-safe, and eliminating the original program's heavy use of global variables.
My question is Do VB6 event handlers run in separate threads? If so how did VB6 ever get away with this? Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
Apartment-Model Threading in Visual Basic
If you want the gritty details, research apartment threading models in COM. VB6 basically uses COM and it's built-in implicity threading models to treat single threads as message-passing entities. It simplifies thread-safety, but underneath you are sacrificing a lot of overhead by basically treating all method calls as queued service calls.
All of your code basically runs in a container that implements COM service calls. If you've ever worked with something written in VB6 in another language, you can interact with them via COM, usually.
Do VB6 event handlers run in separate threads?
Not really, because there aren't separate threads. Your code runs on a single thread, wrapped in the service-like architecture I described above. Most of what you talk to that is threaded is other COM objects which have their own apartments. So to communicate back and forth, you are basically doing RPC calls when the threads talk to each other: you aren't directly manipulating them.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
The "timer" is on a separate thread created for the timer, but when it calls into your code, you are guaranteed not to interrupt any other functions, because the function calls are basically queued one at a time in the thread.
My question is Do VB6 event handlers run in separate threads?
Common answer: No.
Real answer: Yes, if you make nasty Win32 calls to spawn more threads. The odds of doing this correctly are close to zero. I don't think I've ever seen it in real code.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
When the timer wakes up, it puts a message in the UI's queue. When the UI goes idle, it processes the message and runs the event on the UI thread.
You can do the same thing in WinForms if you use the right timer.
To Matt Wilko, DoEvents is VB6 implementing a virtual cooperative multithreading thing. What's a thread, something that can be interupted to run other code. When you use DoEvents you interupt the execution of your code, when the CPU does multithreading it preempts your code. The effect is the same. One done by VB6 runtime and one by the CPU.
The effect is the same. YOU NEED TO SYNCHRONISE ACCESS TO GLOBAL OBJECTS and VARIABLES.
Your event Handlers aren't supposed to run too long. Each event is queued and run one at a time.
Also the way to multithread a VB6 thing is to put other things in a COM Exe file with a asynchronous model. The exe calls back when finished.
Is there anything wrong with creating a window in a separate thread, which will also contain the message loop, then creating an OpenGL Context in another thread?
You should be able to get it to work, if you're careful. See the parallel opengl faq.
Q: Why does my OpenGL application crash/not work when
I am rendering from another thread?
A: The OpenGL context is thread-specific. You have to
make it current in the thread using glXMakeCurrent,
wglMakeCurrent or aglSetCurrentContext, depending on
your operating system.
What you want to do is perfectly possible. Even better, OpenGL contexts can migrate between threads and even be used with multiple windows as long as their pixel format is compatible. The one constraint is, that a OpenGL context can be bound in only one thread at a time and that only a unbound context can be bound.
So you could even create the window and the context in one thread, then unbind the context, create another thread and re-bind the context to the window in the secondary thread. No problem there.
The only thing you must be aware of is, that OpenGL itself doesn't like to be multithreaded. The API itself is more or less thread safe, as only one context can be bound to a thread at a time. But all the bookkeeping required if OpenGL operations spawn over several threads may trigger nasty driver bugs and also has a certain performance hit.
Main (function main is there) thread of my program is reserved for non-GUI tasks. It calls a number of lengthy calculation functions. All implemented GUI's have been doing their work in a separate threads.
I'm now going to implement one more GUI using Qt. Qt documentation says all GUI related tasks should be done in main thread.
In my case, inserting occasional QCoreApplication::processEvents() calls in main thread would be virtually useless due to great delays between them.
Is there any way to overcome this constraint of Qt?
Is it impossible to do something non-GUI related in main thread of Qt program?
No, you should be doing your calculations in a separate thread. As you already mentioned, there is a work-around available in QCoreApplication::processEvents(), but it sounds like you're unable to make that work for you.
If you don't want to have to do all the work of setting up a QThread and moving all your code, you may find that the QtConcurrent::run function is useful - it allows you to run a function asynchronously.
A few pointers: You should try and keep your main (GUI) thread as light as possible. Large amounts of IO or calculations should either be done asynchronously using QtConcurrent::run, or run inside a separate QThread. Depending on the complexity of your code, you may be able to get away with the QtConcurrent method.
It's best to offload the long computations onto other threads so the main GUI thread remains responsive. The old-school uniprocessing way of doing things would be be to make sure your computations never run for too long without polling GUI event handler, but that doesn't scale to multi-cores.
Fortunately Qt has excellent threading support. In the past you'd have to roll-you-own system for e.g farming out tasks to a thread-pool using QThread, QMutex, QWaitCondition etc, but recent Qt releases have made things easier with higher level abstractions like QThreadPool, QtConcurrent::run and QFuture.
I don't know how things will go if you call QApplication::exec() from another thread, which then becomes your gui thread. Just an idea.
(Let us know if it works, it'd be interesting...)
The concept of main thread is not clearly defined in Qt documentation. Actually, the main thread of a process (process that executes the Process.run function) can be different from the main Qt thread (thread that instantiates the first Qt object like a QApplication), although both "main" threads are often the same one.
Example of valid code structure:
function below will run in the process' non-main thread 'thread-1', that will become immediately Qt's main thread.
def startThread1():
app = QApplication(sys.argv)
app.exec_() # enter event loop
code below run in process' main thread, not to be confused with the main Qt and unique GUI thread of the process.
thread1 = Thread(target=self.startThread1)
thread1.start()
input('I am busy until you press enter')