Is it possible to start new threads from a C-MEX file?

15 views (last 30 days)
I would like to start new execution threads from within a C-MEX file. Is this functionality supported?

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 10 Jun 2015
Edited: MathWorks Support Team on 4 Nov 2020
There is no supported implementation of calling a single session of MATLAB in separate threads. However, it is possible to create new threads from a C MEX-file in a supported fashion; as long as those threads do not access MATLAB in any way. Since the MEX API is not thread safe, no MEX API functions can be used in the spawned threads including printf because printf is defined to be mexPrintf in the mex.h header file.
Below are two examples of multithreaded MEX functions on Windows. You can also create multithreaded MEX functions on other platforms, but the API functions for creating threads will be different.
The following is an example of a C MEX-file that creates a new thread using the function _beginthreadex. For details on this function, see:
The code below is adapted from the second example from the link above. Note that this example requires a Microsoft compiler.
#include "mex.h"
#include <windows.h>
#include <stdio.h>
#include <process.h>
unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
while ( Counter < 1000000 )
Counter++;
_endthreadex( 0 );
return 0;
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray*prhs[] )
{
HANDLE hThread;
unsigned threadID;
printf( "Creating second thread...\n" );
/* Create the second thread.*/
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
/* Wait until second thread terminates. If you comment out the line
* below, Counter will not be correct because the thread has not
* terminated, and Counter most likely has not been incremented to
* 1000000 yet.*/
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 1000000; it is-> %d\n", Counter );
/* Destroy the thread object. */
CloseHandle( hThread );
return;
}
Save the code above into a file named create_thread.c. Then execute:\n
mex -setup
and choose a Microsoft compiler. Compile the C-MEX function with:\n
mex create_thread.c
If you execute the MEX-function from the MATLAB command line, you should see the following screen output:\n
Creating second thread...
Counter should be 1000000; it is-> 1000000
It is also possible to have the second thread continue to execute even after the function mexFunction has returned to the MATLAB command prompt. You can then call back into mexFunction and get the results from the second thread.
In this second example, the first time the MEX function is called, pass in the argument 'Init'. This will spawn a second thread. The second time the MEX function is called pass in the argument 'Finish' (or any other string). This will print the counter variable and clean up the thread.\n
#include "mex.h"
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
/*These global variables will be accessible to both threads and will exist
*in the MEX function through multiple calls to the MEX function */
static unsigned Counter;
static HANDLE hThread=NULL;
/*The second thread should not try to communicate with MATLAB at all.
*This includes the use of mexPrintf, which attempts to print to the
*MATLAB command window. */
unsigned __stdcall SecondThreadFunc( void* pArguments ) {
/* loop for 20 seconds */
while ( Counter < 20 ) {
Counter++;
Sleep( 1000L );
}
_endthreadex( 0 );
return 0;
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) {
unsigned threadID;
char *cmd;
/* check for proper number of arguments */
if(nrhs!=1)
mexErrMsgTxt("One input required.");
/* check to make sure the first input argument is a string */
if (!mxIsChar(prhs[0]))
mexErrMsgTxt("Input must be a string.");
/* get command from first input */
cmd = mxArrayToString(prhs[0]);
/* if command is "Init", start the thread, otherwise wait for thread
* to complete */
if (!strcmp(cmd,"Init")) {
/* make sure thread was not started using "mex locked" state */
if (mexIsLocked())
mexErrMsgTxt("Thread already initialized.");
/* lock thread so that no-one accidentally clears function */
mexLock();
/* Create the second thread. */
mexPrintf( "Creating second thread...\n" );
Counter = 0;
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
}
else {
/* make sure that the thread was started using "mex locked" status*/
if (!mexIsLocked())
mexErrMsgTxt("Thread not initialized yet."); /*This function will return control to MATLAB*/
/* wait for thread to finish and get result */
WaitForSingleObject( hThread, INFINITE );
mexPrintf( "Counter should be 20; it is-> %d\n", Counter );
/* Destroy the thread object, free memory, and unlock mex. */
CloseHandle( hThread );
mexUnlock();
}
return;
}
Save the code above into a file named create_async.c. Then execute:\n
mex create_async.c
Execute the following command to spawn the second thread\n
create_async Init
and you should see the following message\n
Creating second thread...
Next, execute the following command to get the results\n
create_async Finish
The program will pause until the second thread has finished executing, this will be approximately 20 seconds from the time the thread was created. You should then see the following message\n
Counter should be 20; it is-> 20

More Answers (0)

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!