LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

multithreading

I am creating a multithreaded application and need to store a string in a thread local variable. I have used CmtGetThreadLocalVar to store and retrieve int's and double's with no problem. For some reason, I am unable to retrieve a string using CmtGetThreadLocalVar after storing it with the same function (i.e. CmtGetThreadLocalVar). Below is a sample created by NI, that I modified slightly to demonstrate the problem. Note that inside the "ThreadFunction" callback, there is a call to the "StringCreate" function, which is suppose to store a string to the thread local variable. After calling the "StringCreate" function, I call ProcessSystemEvents, a short delay, and then attempt to retrieve the string using "CmtGetThreadLocalVar". If you run this code, you will see that the variable "sString" that should contain the last assigned string, does not! Any help would be greatly appreciated


#include
#include
#include "toolbox.h"
#include


int CVICALLBACK ThreadFunction (void *functionData);
void CVICALLBACK StringCreate (char *strToCreate);
void CVICALLBACK StringDiscard (void *threadLocalPtr, int event, void *callbackData, unsigned int threadID);
int tlvHandle;
volatile int quit = 0;
volatile int secondStrCreated = 0;



int main (int argc, char *argv[])
{
int functionId;


if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */

CmtNewThreadLocalVar (sizeof(char *), NULL, StringDiscard, NULL, &tlvHandle);

CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, ThreadFunction, "Secondary Thread", &functionId);

StringCreate ("Main Thread");

while (!secondStrCreated)
{
ProcessSystemEvents ();
Delay (0.001);
}


CmtDiscardThreadLocalVar (tlvHandle);

quit = 1;

CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, functionId, 0);

return 0;
}



int CVICALLBACK ThreadFunction (void *functionData)
{
char sString[MAX_PATHNAME_LEN];


StringCreate ((char *)functionData);

ProcessSystemEvents ();
Delay (1);

CmtGetThreadLocalVar (tlvHandle, sString);

secondStrCreated = 1;

while (!quit)
{
ProcessSystemEvents ();
Delay (0.001);
}



return 0;
}


void CVICALLBACK StringCreate (char *strToCreate)
{
char **tlvStringPtr;

CmtGetThreadLocalVar (tlvHandle, &tlvStringPtr);

*tlvStringPtr = malloc (strlen (strToCreate) + 1);

strcpy (*tlvStringPtr, strToCreate);
}


void CVICALLBACK StringDiscard (void *threadLocalPtr, int event, void *callbackData, unsigned int threadID)
{
char *str = *(char **)threadLocalPtr;

free (str);
}
0 Kudos
Message 1 of 4
(3,645 Views)
Howdy


You will need to access the thread safe variable in the same way as you created in.


int CVICALLBACK ThreadFunction (void *functionData)
{
//the buffer already exists, you're just getting a pointer to the string buffer.
//You can use the string copy functions to copy the string to another string buffer.
char **sString;

StringCreate ((char *)functionData);
ProcessSystemEvents ();

Delay (1);
CmtGetThreadLocalVar (tlvHandle, &sString);
strcpy(buffer,*sString);
secondStrCreated = 1;

while (!quit)
{
ProcessSystemEvents ();
Delay (0.001);
}

return 0;
}


If you use the debugger, you'll see that *sString returns the correct string. I file a report to add retrieving this type of data in the multi-threading application note. I'm assuming that is what you were using as a reference.

Message Edited by bilalD on 05-26-2005 09:05 AM

Bilal Durrani
NI
0 Kudos
Message 2 of 4
(3,613 Views)
Just a thought....

I've created dozens of multithreaded applications, large and small. I don't recall ever using thread safe variables. Whether you declare variables outside or inside your thread function, as long as you manage them, so that nothing outside the thread messes with them, they are by nature thread safe.
0 Kudos
Message 3 of 4
(3,589 Views)
I'm with hendra on this - I also have done several multi-threaded apps in CVI and have yet to use NI's thread local variable functionality - which I suspect may really be a front end to native Win32 thread local storage.

In fact, I never use any of the NI threading functions: I use Win32 API threading and synchronization mechanisms, which work just fine. If your app is going to only ever run on a Win32 box, then I see no reason to use the NI calls. It seems to me that if you know enough to do a Win32 multi-threaded application, you've likely learned how by reading Win32 documentation in the SDK or other non-NI sources, so why not use the native functionality? There's nothing particularly compelling about the way NI mapped the Win32 API to proprietary calls.
Message 4 of 4
(3,555 Views)