Threads

In Max, there are several threads of execution. More...

+ Collaboration diagram for Threads:

Modules

 Critical Regions
 A critical region is a simple mechanism that prevents multiple threads from accessing at once code protected by the same critical region.
 
 Mutexes
 

Macros

#define ATOMIC_INCREMENT(atomicptr)
 increment an atomic int valuereturn value of ATOMIC_INCREMENT and ATOMIC_DECREMENT is the *new* value after performing the operation
 
#define ATOMIC_INCREMENT_BARRIER(atomicptr)
 increment an atomic int value with a memory barrierreturn value of ATOMIC_INCREMENT and ATOMIC_DECREMENT is the *new* value after performing the operation
 
#define ATOMIC_DECREMENT(atomicptr)
 decrement an atomic int valuereturn value of ATOMIC_INCREMENT and ATOMIC_DECREMENT is the *new* value after performing the operation
 
#define ATOMIC_DECREMENT_BARRIER(atomicptr)
 decrement an atomic int value with a memory barrierreturn value of ATOMIC_INCREMENT and ATOMIC_DECREMENT is the *new* value after performing the operation
 

Typedefs

typedef void * t_systhread_mutex
 An opaque mutex handle.
 
typedef void * t_systhread_cond
 An opaque cond handle.
 

Enumerations

enum  e_max_systhread_mutex_flags { SYSTHREAD_MUTEX_NORMAL, SYSTHREAD_MUTEX_ERRORCHECK, SYSTHREAD_MUTEX_RECURSIVE }
 systhread_mutex_new() flags More...
 

Functions

void schedule (void *ob, method fun, long when, t_symbol *sym, short argc, t_atom *argv)
 Cause a function to be executed at the timer level at some time in the future. More...
 
void schedule_delay (void *ob, method fun, long delay, t_symbol *sym, short argc, t_atom *argv)
 Cause a function to be executed at the timer level at some time in the future specified by a delay offset. More...
 
long isr (void)
 Determine whether your code is executing in the Max scheduler thread. More...
 
void * defer (void *ob, method fn, t_symbol *sym, short argc, t_atom *argv)
 Defer execution of a function to the main thread if (and only if) your function is executing in the scheduler thread. More...
 
void * defer_low (void *ob, method fn, t_symbol *sym, short argc, t_atom *argv)
 Defer execution of a function to the back of the queue on the main thread. More...
 
long systhread_create (method entryproc, void *arg, long stacksize, long priority, long flags, t_systhread *thread)
 Create a new thread. More...
 
long systhread_terminate (t_systhread thread)
 Forcefully kill a thread – not recommended. More...
 
void systhread_sleep (long milliseconds)
 Suspend the execution of the calling thread. More...
 
void systhread_exit (long status)
 Exit the calling thread. More...
 
long systhread_join (t_systhread thread, unsigned int *retval)
 Wait for thread to quit and get return value from systhread_exit(). More...
 
long systhread_detach (t_systhread thread)
 Detach a thread. More...
 
t_systhread systhread_self (void)
 Return the thread instance pointer for the calling thread. More...
 
void systhread_setpriority (t_systhread thread, int priority)
 Set the thread priority for the given thread. More...
 
int systhread_getpriority (t_systhread thread)
 Get the thread priority for the given thread. More...
 
short systhread_ismainthread (void)
 Check to see if the function currently being executed is in the main thread. More...
 
short systhread_istimerthread (void)
 Check to see if the function currently being executed is in a scheduler thread. More...
 
short systhread_isaudiothread (void)
 Check to see if the function currently being executed is in an audio thread. More...
 

Variables

BEGIN_USING_C_LINKAGE typedef void * t_systhread
 An opaque thread instance pointer.
 

Detailed Description

In Max, there are several threads of execution.

The details of these threads are highlighted in the article "Event Priority in Max (Scheduler vs. Queue)" located online at http://www.cycling74.com/story/2005/5/2/133649/9742.

Not all of the details of Max's threading model are expounded here. Most important to understand is that we typically deal the scheduler (which when overdrive is on runs in a separate and high priority thread) and the low priority queue (which always runs in the main application thread).

See also
http://www.cycling74.com/twiki/bin/view/ProductDocumentation/JitterSdkSchedQueue
http://www.cycling74.com/story/2005/5/2/133649/9742

Enumeration Type Documentation

systhread_mutex_new() flags

Enumerator
SYSTHREAD_MUTEX_NORMAL 

Normal.

SYSTHREAD_MUTEX_ERRORCHECK 

Error-checking.

SYSTHREAD_MUTEX_RECURSIVE 

Recursive.

Function Documentation

void* defer ( void *  ob,
method  fn,
t_symbol sym,
short  argc,
t_atom argv 
)

Defer execution of a function to the main thread if (and only if) your function is executing in the scheduler thread.

Parameters
obFirst argument passed to the function fun when it executes.
fnFunction to be called, see below for how it should be declared.
symSecond argument passed to the function fun when it executes.
argcCount of arguments in argv. argc is also the third argument passed to the function fun when it executes.
argvArray containing a variable number of t_atom function arguments. If this argument is non-zero, defer allocates memory to make a copy of the arguments (according to the size passed in argc) and passes the copied array to the function fun when it executes as the fourth argument.
Returns
Return values is for internal Cycling '74 use only.
Remarks
This function uses the isr() routine to determine whether you're at the Max timer interrupt level (in the scheduler thread). If so, defer() creates a Qelem (see Qelems), calls qelem_front(), and its queue function calls the function fn you passed with the specified arguments. If you're not in the scheduler thread, the function is executed immediately with the arguments. Note that this implies that defer() is not appropriate for using in situations such as Device or File manager I/0 completion routines. The defer_low() function is appropriate however, because it always defers.

The deferred function should be declared as follows:

1 void myobject_do (myObject *client, t_symbol *s, short argc, t_atom *argv);
See also
defer_low()

Referenced by jit_error_code(), jit_error_sym(), and jit_post_sym().

void* defer_low ( void *  ob,
method  fn,
t_symbol sym,
short  argc,
t_atom argv 
)

Defer execution of a function to the back of the queue on the main thread.

Parameters
obFirst argument passed to the function fun when it executes.
fnFunction to be called, see below for how it should be declared.
symSecond argument passed to the function fun when it executes.
argcCount of arguments in argv. argc is also the third argument passed to the function fun when it executes.
argvArray containing a variable number of t_atom function arguments. If this argument is non-zero, defer allocates memory to make a copy of the arguments (according to the size passed in argc) and passes the copied array to the function fun when it executes as the fourth argument.
Returns
Return values is for internal Cycling '74 use only.
Remarks
defer_low() always defers a call to the function fun whether you are already in the main thread or not, and uses qelem_set(), not qelem_front(). This function is recommended for responding to messages that will cause your object to open a dialog box, such as read and write.

The deferred function should be declared as follows:

1 void myobject_do (myObject *client, t_symbol *s, short argc, t_atom *argv);
See also
defer()
long isr ( void  )

Determine whether your code is executing in the Max scheduler thread.

Returns
This function returns non-zero if you are within Max's scheduler thread, zero otherwise. Note that if your code sets up other types of interrupt-level callbacks, such as for other types of device drivers used in asynchronous mode, isr will return false.
void schedule ( void *  ob,
method  fun,
long  when,
t_symbol sym,
short  argc,
t_atom argv 
)

Cause a function to be executed at the timer level at some time in the future.

Parameters
obFirst argument passed to the function fun when it executes.
funFunction to be called, see below for how it should be declared.
whenThe logical time that the function fun will be executed.
symSecond argument passed to the function fun when it executes.
argcCount of arguments in argv. argc is also the third argument passed to the function fun when it executes.
argvArray containing a variable number of t_atom function arguments. If this argument is non-zero, defer allocates memory to make a copy of the arguments (according to the size passed in argc) and passes the copied array to the function fun when it executes as the fourth argument.
Remarks
schedule() calls a function at some time in the future. Unlike defer(), the function is called in the scheduling loop when logical time is equal to the specified value when. This means that the function could be called at interrupt level, so it should follow the usual restrictions on interrupt-level conduct. The function fun passed to schedule should be declared as follows:
1 void myobject_do (myObject *client, t_symbol *s, short argc, t_atom *argv);
Remarks
One use of schedule() is as an alternative to using the lockout flag.
See also
defer()
void schedule_delay ( void *  ob,
method  fun,
long  delay,
t_symbol sym,
short  argc,
t_atom argv 
)

Cause a function to be executed at the timer level at some time in the future specified by a delay offset.

Parameters
obFirst argument passed to the function fun when it executes.
funFunction to be called, see below for how it should be declared.
delayThe delay from the current time before the function will be executed.
symSecond argument passed to the function fun when it executes.
argcCount of arguments in argv. argc is also the third argument passed to the function fun when it executes.
argvArray containing a variable number of t_atom function arguments. If this argument is non-zero, schedule_delay() allocates memory to make a copy of the arguments (according to the size passed in argc) and passes the copied array to the function fun when it executes as the fourth argument.
Remarks
schedule_delay() is similar to schedule() but allows you to specify the time as a delay rather than a specific logical time.
1 void myobject_click (t_myobject *x, Point pt, short modifiers)
2 {
3  t_atom a[1];
4  a[0].a_type = A_LONG;
5  a[0].a_w.w_long = Random();
6  schedule_delay(x, myobject_sched, 0 ,0, 1, a);
7 }
8 
9 void myobject_sched (t_myobject *x, t_symbol *s, short ac, t_atom *av)
10 {
11  outlet_int(x->m_out,av->a_w.w_long);
12 }
See also
schedule()
long systhread_create ( method  entryproc,
void *  arg,
long  stacksize,
long  priority,
long  flags,
t_systhread thread 
)

Create a new thread.

Parameters
entryprocA method to call in the new thread when the thread is created.
argAn argument to pass to the method specified for entryproc. Typically this might be a pointer to your object's struct.
stacksizeNot used. Pass 0 for this argument.
priorityPass 0 for default priority. The priority can range from -32 to 32 where -32 is low, 0 is default and 32 is high.
flagsNot used. Pass 0 for this argument.
threadThe address of a t_systhread where this thread's instance pointer will be stored.
Returns
A Max error code as defined in e_max_errorcodes.
long systhread_detach ( t_systhread  thread)

Detach a thread.

After detaching a thread you cannot call systhread_join() on it.

Parameters
threadThe thread to join.
Returns
A Max error code as defined in e_max_errorcodes.
Remarks
You should either call systhread_join() on a thread or systhread_detach() to allow the system to reclaim resources.
void systhread_exit ( long  status)

Exit the calling thread.

Call this from within a thread made using systhread_create() when the thread is no longer needed.

Parameters
statusYou will typically pass 0 for status. This value will be accessible by systhread_join(), if needed.
int systhread_getpriority ( t_systhread  thread)

Get the thread priority for the given thread.

Parameters
threadThe thread for which to find the priority.
Returns
The current priority value for the given thread.
short systhread_isaudiothread ( void  )

Check to see if the function currently being executed is in an audio thread.

Returns
Returns true if the function is being executed in an audio thread, otherwise false.
short systhread_ismainthread ( void  )

Check to see if the function currently being executed is in the main thread.

Returns
Returns true if the function is being executed in the main thread, otherwise false.
short systhread_istimerthread ( void  )

Check to see if the function currently being executed is in a scheduler thread.

Returns
Returns true if the function is being executed in a scheduler thread, otherwise false.
long systhread_join ( t_systhread  thread,
unsigned int *  retval 
)

Wait for thread to quit and get return value from systhread_exit().

Parameters
threadThe thread to join.
retvalThe address of a long to hold the return value (status) from systhread_exit().
Returns
A Max error code as defined in e_max_errorcodes.
Remarks
If your object is freed, and your thread function accesses memory from your object, then you will obviously have a memory violation. A common use of systhread_join() is to prevent this situation by waiting (in your free method) for the thread to exit.
t_systhread systhread_self ( void  )

Return the thread instance pointer for the calling thread.

Returns
The thread instance pointer for the thread from which this function is called.
void systhread_setpriority ( t_systhread  thread,
int  priority 
)

Set the thread priority for the given thread.

Parameters
threadThe thread for which to set the priority.
priorityA value in the range -32 to 32 where -32 is lowest, 0 is default, and 32 is highest.
void systhread_sleep ( long  milliseconds)

Suspend the execution of the calling thread.

Parameters
millisecondsThe number of milliseconds to suspend the execution of the calling thread. The actual amount of time may be longer depending on various factors.
long systhread_terminate ( t_systhread  thread)

Forcefully kill a thread – not recommended.

Parameters
threadThe thread to kill.
Returns
A Max error code as defined in e_max_errorcodes.
  Copyright © 2015, Cycling '74