Skip to content

PassingArgumentsToThreads

Peter Corke edited this page Sep 19, 2018 · 1 revision

Passing arguments to threads

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.

Defining the argument to pass

In order to pass an argument to a thread we must define the struct in two places.

Define it in the code.

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.

Inform codegen about entry-point arguments

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.

Safe concurrency

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:

  1. we might be partway through reading a structure element when another thread changes its value, leading to a corrupt or inconsistent value
  2. 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.