微波EDA网,见证研发工程师的成长!
首页 > 测试测量 > 测试测量技术文库 > LabWindows?/CVI中的多线程技术

LabWindows?/CVI中的多线程技术

时间:12-23 来源:互联网 点击:

函数。利用这些函数可以创建任何类型的线程安全变量。因为,传递到函数中的参数在类型上是通用的,而且不提供类型安全。通常,你不会直接调用LabWindows/CVI Utility Library中的线程安全变量函数。

LabWindows/CVI Utility Library中的头文件中包含了一些宏,它们提供了配合Utility Library函数使用的类型安全的封装函数。除了提供类型安全,这些宏还帮助避免了多线程编程中的其它两个常见错误。这些错误是在访问数据后忘记释放锁对象,或者是在前面没有获取锁对象时试图释放锁对象。使用DefineThreadSafeScalarVar和DefineThreadSafeArrayVar宏来创建线程安全变量和类型安全的函数供使用和访问。如果需要从多个源文件中访问线程安全变量,请在include(.h)文件中使用DeclareThreadSafeScalarVar或者DeclareThreadSafeArrayVar宏来创建访问函数的声明。DefineThreadSafeScalarVar(datatype,VarName,maxGetPointerNestingLevel)宏创建以下访问函数:

int InitializeVarName (void);
void UninitializeVarName (void);
datatype *GetPointerToVarName (void);
void ReleasePointerToVarName (void);
void SetVarName (datatype val);
datatype GetVarName (void);

注意事项:这些宏使用传递进来的第二个参数(在这个例子中为VarName)作为标识来为线程安全变量创建自定义的访问函数名称。

注意事项:maxGetPointerNestingLevel参数将在“检测GetPointerToVarName不匹配调用”一节中进行进一步讨论。

在第一次访问线程安全变量前首先调用一次(只在一个线程里)InitializeVarName函数。在程序中止前调用UninitializeVarName函数。如果需要对变量当前的值进行更改(如,增加一个整数的值),那么请调用GetPointerToVarName函数,更改变量值,然后调用ReleasePointerToVarName函数。在同一个线程中,可以多次调用GetPointerToVarName函数(在后续的调用中不会发生阻塞),但是必须调用相同次数的ReleasePointerToVarName函数与GetPointerToVarName一一对应。如果在相同的线程中,调用了ReleasePointerToVarName函数,而前面没有与之相匹配的GetPointerToVarName调用,那么ReleasePointerToVarName将会报告一个run-time error错误。

如果需要对变量值进行设定而不需要考虑其当前值,那么请调用SetVarName函数。如果需要获得变量的当前值,请调用GetVarName函数。需要了解的一点是,在GetVarName从内存中读出变量值后而在其将变量值返回给你前,变量的值是有可能改变的。

下面的代码显示了如何使用线程安全变量作为前面例子中提到的计数变量。

DefineThreadSafeScalarVar (int, Count, 0);
int CVICALLBACK ThreadFunction (void *functionData);

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

InitializeCount();
CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, ThreadFunction, NULL, &functionId);
countPtr = GetPointerToCount();
(*countPtr)++;
ReleasePointerToCount();
CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, functionId, 0);
UninitializeCount();
return 0;
}
int CVICALLBACK ThreadFunction (void *functionData)
{
int *countPtr;

countPtr = GetPointerToCount();
(*countPtr)++;
ReleasePointerToCount();
return 0;
}

使用数组作为线程安全变量

DefineThreadSafeArrayVar宏与DefineThreadSafeScalarVar宏相似,但是它还需要一个额外的参数来指定数组中元素的个数。同时,与DefineThreadSafeScalarVar不同,DefineThreadSafeArrayVar没有定义GetVarName和SetVarName函数。下面的声明定义了有10个整数的线程安全数组。
DefineThreadSafeArrayVar (int, Array, 10, 0);

将多个变量结合成单个线程安全变量

如果有多个彼此相关的变量,那么必须禁止两个线程同时对这些变量进行修改。例如,有一个数组和记录数组中有效数据数目的count变量。如果一个线程需要删除数组中的数据,那么在另一个线程访问数据前,必须对数组和变量count值进行更新。虽然可以使用单个LabWindows/CVI Utility Library线程锁来对这两种数据的访问保护,但是更安全的做法是定义一个结构体,然后使用这个结构体作为线程安全变量。下面的例子显示了如何使用线程安全变量来安全地向数组中填加一个数据。

typedef struct {
int data[500];
int count;
} BufType;

DefineThreadSafeVar(BufType, SafeBuf);

void StoreValue(int val)
{
BufType *safeBufPtr;
safeBufPtr = GetPointerToSafeBuf();
safeBufPtr->data[safeBufPtr->count] = val;
safeBufPtr->count++;
ReleasePointerToSafeBuf();
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top