Your object’s methods may be called at interrupt level. More...
|typedef void *||t_qelem|
|A qelem. |
|void *||qelem_new (void *obj, method fn)|
|Create a new Qelem. |
|void||qelem_set (void *q)|
|Cause a Qelem to execute. |
|void||qelem_unset (void *q)|
|Cancel a Qelem's execution. |
|void||qelem_free (void *x)|
|Free a Qelem object created with qelem_new(). |
|void||qelem_front (void *x)|
|Cause a Qelem to execute with a higher priority. |
Your object’s methods may be called at interrupt level.
This happens when the user has Overdrive mode enabled and one of your methods is called, directly or indirectly, from a scheduler Clock function. This means that you cannot count on doing certain things—like drawing, asking the user what file they would like opened, or calling any Macintosh toolbox trap that allocates or purges memory—from within any method that responds to any message that could be sent directly from another Max object. The mechanism you’ll use to get around this limitation is the Qelem (queue element) structure. Qelems also allow processor-intensive tasks to be done at a lower priority than in an interrupt. As an example, drawing on the screen, especially in color, takes a long time in comparison with a task like sending MIDI data.
A Qelem works very much like a Clock. You create a new Qelem in your creation function with qelem_new and store a pointer to it in your object. Then you write a queue function, very much like the clock function (it takes the same single argument that will usually be a pointer to your object) that will be called when the Qelem has been set. You set the Qelem to run its function by calling qelem_set().
Often you’ll want to use Qelems and Clocks together. For example, suppose you want to update the display for a counter that changes 20 times a second. This can be accomplished by writing a Clock function that calls qelem_set() and then reschedules itself for 50 milliseconds later using the technique shown in the metronome example above. This scheme works even if you call qelem_set() faster than the computer can draw the counter, because if a Qelem is already set, qelem_set() will not set it again. However, when drawing the counter, you’ll display its current value, not a specific value generated in the Clock function.
Note that the Qelem-based defer mechanism discussed later in this chapter may be easier for lowering the priority of one-time events, such as opening a standard file dialog box in response to a read message.
If your Qelem routine sends messages using outlet_int() or any other of the outlet functions, it needs to use the lockout mechanism described in the Interrupt Level Considerations section.
|void qelem_free||(||void *||x||)|
Free a Qelem object created with qelem_new().
Typically this will be in your object's free funtion.
|x||The Qelem to destroy.|
|void qelem_front||(||void *||x||)|
Cause a Qelem to execute with a higher priority.
This function is identical to qelem_set(), except that the Qelem's function is placed at the front of the list of routines to execute in the main thread instead of the back. Be polite and only use qelem_front() only for special time-critical applications.
|x||The Qelem whose function will be executed in the main thread.|
|void* qelem_new||(||void *||obj,|
Create a new Qelem.
|obj||Argument to be passed to function fun when the Qelem executes. Normally a pointer to your object.|
|fn||Function to execute.|
|void qelem_set||(||void *||q||)|
Cause a Qelem to execute.
|q||The Qelem whose function will be executed in the main thread.|