-
Notifications
You must be signed in to change notification settings - Fork 1
PassingArgumentsToThreads
The C signature for a MATLAB entry-point function is typically
void thread1(void)
STL assumes that arguments passed to threads are MATLAB structs, since these are very general.
In order to pass an argument to a thread we must define the struct in two places.
vars.a = 1
vars.b = 2
vars.mutex = stl.mutex('vars')
coder.cstructname(vars, 'arg_type')
The generated file user_types.h
will now contain this definition
/* Type Definitions */
#ifndef typedef_arg_type
#define typedef_arg_type
typedef struct {
double a;
double b;
int mutex;
} arg_type;
#endif
and the C code will contain an instance of this structure.
Define the same type using coder
methods:
arg_t = coder.newtype('struct', struct( ...
'a', coder.newtype('double'), ...
'b', coder.newtype('double'), ...
'mutex', coder.newtype('int32') ));
and this definition must match that given in the code.
This causes user_types.h
to contain this definition
#ifndef typedef_struct0_T
#define typedef_struct0_T
typedef struct {
double a;
double b;
int mutex;
} struct0_T;
Now pass this definition object arg_t
to codegen
to inform it about the argument passed to each entry-point
codegen user.m thread1.m -args arg_t thread2.m -args arg_t -config cfg
Note that the -args
option comes after the MATLAB file name it is associated with.
The function signature is now
void thread1(struct struct0_T *arg)
so the structure is passed by reference.
The structure defined in user.m
vars.a = 1
vars.b = 2
vars.mutex = stl.mutex('vars')
coder.cstructname(vars, 'arg_type')
stl.launch('thread1', vars)
is passed by reference to thread.m
function thread1(vars)
Note:
- Both instances refer to the same object in memory. The user main function can pass this struct by reference to multiple threads.
- We can define multiple structs in this fashion, and pass different structs to different threads if we wish.
Since the arguments are used in multiple threads we need to be careful when we read and write this shared data. There are a number of potential hazards:
- we might be partway through reading a structure element when another thread changes its value, leading to a corrupt or inconsistent value
- two threads might attempt to write the same variable simultaneously
To protect against this we would normally use a mutex. We can create an STL mutex and assign its id
to an element of the struct. Then before we read or write any other elements of the struct we first acquire the mutex
stl.mutex_lock(vars.mutex)
.
.
do stuff
.
.
stl.mutex_unlock(vars.mutex)
Ideally the mutex should not be held for too long by any one thread, so the mutex block could make copies of shared variables to prevent problem 1 above from occuring.