New script = new message thread?
-
As the name suggests, does making a new script actually use another message thread rather than the interface one?
I have a heavy computation loop that makes the interface thread very busy (can go over 30sec depending on the machine)
So I'd like to move my function somewhere else so the interface doesn't freeze during that time.
It is important to keep in mind that this function updates a progress bar on the interface. -
@ustk If the script is doing realtime stuff then it will be in the realtime thread, unless it's deferred.
-
@d-healey Yeah I understand that. But, unless I'm wrong, there are different threads created per "type". Like several real-time, several messages (well, maybe not for the real-time one)... I don't remember where but these days while debugging, Xcode told me I had 7 threads opened, hence my question. I don't need real-time stuff, just separated message threads, if such a thing exists of course... There should be a possibility of doing different things asynchronously.
After all, the server thread and file thread are using some kind of message thread no?
-
You have these threads available in HISE:
- audio thread: high priority, scheduled by the OS
- sample loading thread: also high priority, but a custom thread that is used to fetch the samples. It's also used for any kind of heavyweight background task when the engine is suspended (eg. normalising a big samplemap)
- scripting thread: this is also a custom thread which runs all scripted callbacks. It is used by all script processors but has a priority system (so a compilation task will be prioritized over a paint routine)
- message thread: scheduled by the OS handles all UI stuff
- OpenGL thread: scheduled by the OS for rendering OpenGL (this is synchronized with the message thread)
plus a few other occasional threads (server callbacks, etc).
If you have a super long method in a script(eg. analysing 500 audio files), this will normally be executed on the scripting thread (if its launched by a control callback), and thus block any other execution of a script callback - however the message thread will continue to work simultaneously (otherwise your mouse would freeze).
Spawning off a new thread is not super trivial because you will need some form of synchronisation to the scripting thread (the reason that it's all being executed in one thread is to reduce the almost infinitely large number of edge cases that occur when running multiple scripts at once ) and you would then either live with the instability of a unsynchronised system or go back to square one if you block the scripting thread while the new thread is busy.
If you already have a progress bar, can't you just add a cancel button and then do this in your method:
inline function mySuperLongMethod() { for(i = 0; i < 100000; i++) { if(cancelButton.getValue()) break; // do some nasty stuff here } }
-
@Christoph-Hart Thanks for the clarification.
Yeah, I thought of adding such a cancel button, but, while my loop is running, I have access to nothing. No button, no graphic stuff... In fact, even the progress bar wouldn't move with a paint routine, so I had to make a hidden panel that changes its position...The loop in question is a correlation algorithm, hence making a nested loop onto a selection on my almost "1sec" sample array/buffer. So this nested loop is taking full focus of the interface until it is done. and sliding the progress bar/panel is the only thing that works during this time. Meters are freezing too of course.
-
@Christoph-Hart What if I put the heavy stuff in the audio thread, knowing that I don't use it at computation time?
Can this cause drop-outs for other applications?It is probably not possible, but having a lower priority thread just for heavy stuff would be cool.. Then we could use a timer to checks when it is done, and nothing is going back and forth between the threads, except a global flag.
How other applications are working then? When their interface doesn't freeze during heavy computation? Don't have examples but, be it audio, graphics or data computing, they exists.
-
I have a question, slightly related to this thread stuff I think...
I have a panel with a preload callback, in that callback I start a timer, which repaints the panel to create a preload animation. By starting the timer manually I see the animation play, but when the preloader starts the timer the animation freezes after one frame until the loading is complete. How can I get my animation to play while the samples are loaded?
This is almost the script I'm using
sofiawoodwinds/Scripts/preloadBar.js at master · davidhealey/sofiawoodwinds
Contribute to davidhealey/sofiawoodwinds development by creating an account on GitHub.
GitHub (github.com)
-
@d-healey This is kind of exactly the issue I have...
I came up with simply moving the panel's position instead of updating its paint routine.
As Chris said, the paint routine has a lower priority, so it will repaint only when the highest priority things are done.
But moving a component works, it certainly has a higher priority over a paint routine AND the sample loading or other heavy functions like in my case... Which is weird, because it is still the script thread that moves the component -
@ustk said in New script = new message thread?:
As Chris said, the paint routine has a lower priority,
But the code I'm using is Christoph's :cat_face_with_tears_of_joy:
-
@d-healey And my solution might not work in your case. Because on my side, the heavy stuff is in the same script thread. But in your case, it is a higher priority one. Test and report :)
-
@ustk It won't work for me because I need to repaint things (that script I linked too is not 100% the same as the one I'm using).
-
I assume the new BackgroundTask class is related to this thread? Can it be used to solve my preloader issue? I found an old old forum post where someone had the same issue.
-
@d-healey Yeah it is totally related. If I can build I'm trying today ;)
-
@d-healey I think there‘s a glitch that prevents the timer from being started in your case so spawning another thread won‘t solve it.
Is this reproducable with the code you‘ve linked?
-
@christoph-hart I'll check and make a snippet
-
The above preloadBar code works. I've figured it's something to do with my paint routine, it has a loop in it so I'm investigating that angle now.
-
Is there a way I can trigger the preload callback for testing purposes without just switching sample maps?
-
@ustk said in New script = new message thread?:
@d-healey
Yeah it is totally related.Sorry for misleading you!
-
@ustk said in New script = new message thread?:
@ustk said in New script = new message thread?:
@d-healey
Yeah it is totally related.Sorry for misleading you!
Actually I think it is related, but in a different way. I made another project to test my preload animation and it works fine. I did some more tests in my main project and I think it's because I'm doing other things when the preset loads, those things are "blocking" the animation. So I'm thinking if I move those things to a background task it might solve it.
-
I finally solved my preload issue. Not 100% sure what is causing it but moving my sample loading into the post preset callback made it work.