Multithreading Utilities
Availability LightWave 6.0 | Component Layout, Modeler | Header lwmtutil.h
The multithreading global supplies a mutex (mutual exclusion) mechanism for managing threaded execution of your plug-in. LightWave may invoke your plug-in from multiple threads simultaneously, which has the effect of threading your code. But when doing certain things, for example when reading and writing global data, the threads of your code should be executed one at a time, rather than all at once. The mutex mechanism is a way for the threads of your code to cooperate in waiting for one another.
Think of a mutex as a dressing room, a place where a thread can have some privacy. Any
time your plug-in needs to do something synchronously (one thread at a time), you ask to
be let into the dressing room by calling lock
. If another thread (another
"you") is already in that dressing room, your thread waits until the other
thread is done. Then your thread gets the dressing room, and other threads that want that
dressing room must wait for you to finish. When you're finished, you call unlock
.
The LWMTUtilID returned by the create
function allows you to use up to 10
separate mutexes. These are numbered from 0 to 9 and are passed as the second argument to lock
and unlock
. You might think of these as 10 different dressing rooms.
Multithreading is a complex topic. If you're unfamiliar with it, you're encouraged to seek out a general programming text that discusses the writing of thread-safe code.
Global Call
LWMTUtilFuncs *mtutil; mtutil = global( LWMTUTILFUNCS_GLOBAL, GFUSE_TRANSIENT );
The global function returns a pointer to an LWMTUtilFuncs.
typedef struct st_LWMTUtilFuncs { LWMTUtilID (*create) (void); void (*destroy)(LWMTUtilID mtid); int (*lock) (LWMTUtilID mtid, int mutexID); int (*unlock) (LWMTUtilID mtid, int mutexID); } LWMTUtilFuncs;
mtid = create()
- Returns an LWMTUtilID that can be used by the lock and unlock functions. The return
value is NULL if
create
fails. destroy( mtid )
- Free resources allocated by
create
. ok = lock( mtid, index )
- Blocks until the mutex becomes available. Returns true if successful, or false if the
lock couldn't be executed for some reason. The index is an integer from 0 to 9 that
identifies which of the ten mutexes to lock. If another thread has already called
lock
for this mutex, the calling thread waits until the other thread callsunlock
. ok = unlock( mtid, index )
- Release the mutex. If another thread has been waiting for this mutex, that thread will execute. Returns true if successful, otherwise false.
Example
This code fragment outlines the sequence of steps you'd take to use a mutex.
#include <lwmtutil.h> LWMTUtilFuncs *mtutil; LWMTUtilID mtid; mtutil = global( LWMTUTILFUNCS_GLOBAL, GFUSE_TRANSIENT ); if ( !mtutil ) ...global not available, do this some other way... /* create the mutex */ mtid = mtutil->create(); ... /* enclose critical code (code that must run synchronously) in matching lock()/unlock() calls */ if ( mtutil->lock( mtid, 0 )) { ...do something that can't be threaded... mtutil->unlock( mtid, 0 ); } ... /* free the mutex when you no longer need it */ if ( mtid ) mtutil->destroy( mtid );