defer - deferlow
Hi everybody!
could you explain to me the specific use of defer
and deferlow
, and in which context it is used? thank you
let´s start with defer, which is relatively simple.
if you are in overdrive and connect
[metro]
[defer]
metro will output its data into the high priority thread of max runtime, but after defer it will be moved back to the main thread again. (to do the opposite you can use pipe 0. or del 0.)
so for example i sometimes do this:
[sequencer clocked, timecritical data in overdrive]
/ /
[defer] [complicated math for audio DSP]
/
[complicated math for GUI object]
to free up some space in the scheduler thread.
some other things are more on a trial and error basis. for example defer and deferlow sometimes fix issues with loading files on patch init or queueing bugs around [bpatcher]
there is a good article somewhere here about all this stuff.
One source of information on the scheduler vs low-priority threads:
https://cycling74.com/articles/event-priority-in-max-scheduler-vs-queue/
You might also have a look at the cousin object [jit.qball].
When you use defer objects, keep in mind this possible side effect: a carefully sequenced [t b b i b] will execute correctly in the high priority thread when triggered by, say, a MIDI event; now, if you connect a [defer]/[deferlow] on the rightmost outlet, then the order of execution will not be guarranteed.
@roman as I understand it, defer is used to switch from high priority thread to main thread, and pipe 0. or del 0. to do the reverse process. But why is the complicated math for audio DSPs (I imagine processes using FFT) left out of the high priority thread? Couldn't there be glitch problems in this case?
These are three different threads:
- the audio thread (MSP) is generally the highest priority
- the high priority Max events thread (things triggered by MIDI, [metro], etc.)
- the low priority Max events thread (things triggered by the mouse, [qmetro], etc.)
On this topic, the discussion I linked above is excellent.
The article Jean-Francois links to explains this, but the other wrinkle is that if you select "Audio Interrupt" in the audio status settings, then the high priority thread *is* the audio thread (thus there are only two threads), and that thread alternates between handing events on the high priority event queue and rendering the dsp vector. This may or may not be what you want, so worth testing out.
The article Jean-Francois links to explains this, but the other wrinkle is that if you select "Audio Interrupt" in the audio status settings, then the high priority thread is the audio thread (thus there are only two threads), and that thread alternates between handing events on the high priority event queue and rendering the dsp vector.
How does deferlow and defer differ in the case of the two threads only? Do they put events at the tail (for the former) and the front (for the latter) of the high priority thread?
...of the main thread.
Aha, so there's only the main thread and the audio thread?
what do you mean with "there is"? defer puts things from the high priority down into the main thread. in case the high priority exists, otherwise it does nothing.
the main thread always exists, only the high priority is optional. (i also believe it would be correct to say that the audio thread is "optional")
the article jfc linked to has it all. it might be a bit much at frist, but you can use it as reference in the future.
simple experiment; run an uzi 50000000 into a button object, and then see what happens to cycle~ and the mouse cursor for all the different combinations of audio on/off, overdrive on/off, and interrupt on/off.
the main thread always exists, only the high priority is optional.
I think we mean the same thing. Put differently, with SIAI there is no high priority thread (or in other words the high priority thread is never used). Or to be precise with the naming conventions, there is no scheduler thread (being used) with SIAI.

I think you have it backwards a bit. When you run audio in interrupt, both the audio and scheduler thread continue to exist as far as how Max behaves (along with the main thread), but under the hood, they are actually the same thread cutting round robin between them. A signal vector of audio gets rendered, then the scheduler thread runs, and on an on. It doesn't change anything about how defer, pipe, or deferlow work. It just means a bunch of the scheduler thread settings in preferences don't mean anything. (ie how frequently it runs, it always runs once a vector).
This is how it always works in Max for Live btw.
exactly, it might be technically incorrect, but it is more useful to think of them as two independent threads, just with a different relation to each other as without interrupt on.
as a compromise i would offer the following explanation: with interrupt on, the scheduler runs inside the audio thread.
funfact: when using the NRT driver, interrupt must always be on to retain a scheduler clock, but an actual interruption of the audio signal will under no circumstances occur. :P
only in NRT you can have an ideal system, able to perform anything.
Thank you very much for the info and explanations, guys. Will have to study it more before I find it intuitive I guess.
Well, there is nothing intuitive about Max and threads, so it's quite understable that would be confused. And for reason I don't understand, the documentation on this is (IMHO) not as clear or extensive as it should be. These sorts of questions come up all the time.
In one way, it's great that Max (unlike Pd) has multiple threads: you get to do visuals and UI stuff that would be too draining in an audio/scheduler thread.
In another way - it's awful: the visual patcher becomes a terrible representation of what's going on in terms of control and event flow as soon as you add the two threads to the picture, especially as we have both explict thread movers and imlicit (e.g., messages into JS or other objects that do a defer with no visual representation of it.)
Might be worth mentioning that Pd only has one thread. They chose the opposite tradeoffs: no fancy pants visuals in a separate thread, but what you see is really what you get for execution flow.
Yeah I agree Iain. There should be definitive, easily accessible documentation on scheduling that leaves no door open to interpretation or doubt. It's essential. I mean even the scheduler settings could use clarifications with practical usecases and examples.
Good to know about Pd. Thanks.
Maybe I've missed it, but the only link I've seen in this thread is to the article from 2004. While this article is great, if you feel that you're still in doubt, I can highly recommend
The official documentation, which explains every single option, defer/deferlow, best practices, etc.
A 20min video by Timothy Place explaining the Max threading model and its pitfalls
The first part of the Min-Devkit guide on threading (before it goes into the C++ details), which condensed the info from the video into a few short paragraphs