在 C 程序中考虑以下情况。我们有一组函数,让通用的函数
void needs_param (void * param, ...);
,它取决于某个参数param
的值。参数param
由函数计算,例如
void compute_param (..., void * param);
我们希望尽可能地将param
(类型,大小,值,...)的细节隐藏到调用者,其中调用者是一个使用函数的函数{{ 1}}和compute_param
。如果您可以自由修改needs_param
和needs_param
,如何最有效和线程安全实现?
我已考虑并排除了以下可能性:
a:因为我们可以自由修改compute_param
,所以一种方法是传递needs_param
及其参数而不是gen_param
,并让param
计算needs_param
。但是param
计算成本很高,并且需要多次作为其他函数的参数。
b:我们可以将param
实现为
compute_param
但是,这不是线程安全的,使用void * compute_param (...) {
static param_type param = ...
return ¶m;
}
我们必须保护呼叫
openmp
会严重影响线程程序的性能。
C:一种解决方案是使用malloc / free
#pragama omp critical
{
void * param = compute_param (...)
}
通过释放分配的内存来加重调用者的负担,同时由于堆内存昂贵而效率低下。
d:使用void compute_param (..., void * param) {
param = malloc (sizeof (param_type));
....
*param = ...
}
,例如
alloca
,需要有关调用者空间中void * param = alloca (param_size);
compute_param (..., param);
...
needs_param (param, ...);
大小的信息,我们希望隐藏这些信息。
你有什么建议吗?
答案 0 :(得分:3)
我建议你使用一种称为“不透明指针”的解决方案。例如,它广泛用于Windows内核世界中,以隐藏来自调用者的对象。
首先定义指针类型typedef void* pobject;
。
然后,您只能在程序中以这种方式操纵对象。许多函数如pobject create_object()
,use_object(pobject)
和free_object(pobject)
都使用此技术。
要确保可以安全地操作对象,请在对象本身中添加互斥锁。您还可以添加第一个成员,对象的大小,以快速检查对象的性质(是否被其他人操纵?)。
然后,在函数中,您确实定义了像typedef struct { } object_int, *pobject_int
这样的对象。在每个操作它的函数中,只需将不透明指针从pobject
转换为pobject_int
。
它确实会强制您使用堆,但如果您不想与调用者共享有关对象的任何信息,那么这是最合适的解决方案。