Using Thread Safe Queues to Protect Data
Using the LabWindows/CVI Utility Library thread safe queue, you can safely pass data between threads. You typically use a thread safe queue when your program contains one thread that generates an array of data and another thread that must operate on the array of data. An example of such a program is one in which a secondary thread acquires the data while the main thread reads the data when it is available and then analyzes and/or displays the data. A thread safe queue has the following advantages over a thread safe variable of an array type.
- Internally, thread safe queues use a locking scheme in which one thread can read from the queue at the same time that another thread is writing to the queue. For example, reader and writer threads do not block each other.
- You can configure a thread safe queue for event-based access. You can register a reader callback that is called when a certain amount of data is available in the queue and/or a writer callback that is called when a specified amount of space is available in the queue.
- You can configure a thread safe queue to automatically grow if data is added when it is already full.
The following code shows how a thread uses a thread safe queue to pass data to another thread. The main thread uses a callback to read the data when it is available.
int queue;
int panelHandle;
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((panelHandle = LoadPanel(0, "DAQDisplay.uir", PANEL)) < 0)
return -1;
/* create queue that holds 1000 doubles and grows if needed */
CmtNewTSQ(1000, sizeof(double), OPT_TSQ_DYNAMIC_SIZE, &queue);
CmtInstallTSQCallback (queue, EVENT_TSQ_ITEMS_IN_QUEUE, 500, QueueReadCallback, 0, CmtGetCurrentThreadID(), NULL);
CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, DataAcqThreadFunction, NULL, NULL);
DisplayPanel (panelHandle);
RunUserInterface();
. . .
return 0;
}
void CVICALLBACK QueueReadCallback (int queueHandle, unsigned int event, int value, void *callbackData)
{
double data[500];
CmtReadTSQData (queue, data, 500, TSQ_INFINITE_TIMEOUT, 0);
}