Making sure miqt is safe with Go routines #207
Replies: 2 comments 3 replies
-
@mappu I implemented a solution that solved it for my case. would you please check it, maybe it's useful enough to include it in the |
Beta Was this translation helpful? Give feedback.
-
Goroutines are really great, but they do not magically prevent data races. If you have multiple goroutines all updating the same shared variable, you still must either (A) protect it with a mutex or else (B) serialize access into a single thread (like Qt's thread affinity). Therefore, even in Go, you still must somewhat know what thread your code is running on. Architecting a large Qt/C++ program to avoid these issues is, I think, a skill that comes with practice. It can help a lot to split a function into its UI-part and logic-part. It's also important not to block the main UI thread as this can cause the UI to appear unresponsive. C++ has some tricks in its "favour" - (1) signal/slots can also safely cross QThread boundaries; and (2) making a QThread is cumbersome so you don't do it often, and when you do, usually know exactly what thread your function is running on. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
While using Miqt for a new project I noticed a pattern I would like to demo here. I would like some help planning how to avoid falling into it.
mainthread.Wait
to wrap logic that executes outside of the main thread to run it safely.mainthread.Wait
So now I noticed that every function that mentions
qt6
package or any struct that's based on it has to be wrapped inmainthread.Wait
otherwise the program just panics. Or run my whole program in one Thread which strips Go from it's most useful feature: Goroutines.What do you recommend to do in this case? any moderately complex program will have many execution paths that may or may not be running from the mainthread and wrapping every part of the logic in
wait
will make it look unnecessarily complex. I'm also not sure what happens ifwait
is called from the main thread. I guess the program just hangs?Edit: Yes calling
mainthread.Wait
twice will hang the program. This means there is no gurantee one execution path can call it then continue to call another function that will callwait
again and the program will stop responding.Edit2: I think I can avoid that by serializing the changes to the UI through a Go channel (chan func()) and have a function consuming from the channel and executing the function with
mainthread.Wait
.Edit3: This solution worked. with one caveat. when trying to enqueue a UI change from another UI change. the channel will block as the loop consuming is trying to push to the channel. the solution is to make it buffered channel to allow pushing without blocking in nested UI changes calls
Beta Was this translation helpful? Give feedback.
All reactions