C 避免线程安全结构成员访问的get/set函数中的代码重复

C 避免线程安全结构成员访问的get/set函数中的代码重复,c,struct,pthreads,C,Struct,Pthreads,我正在用多个文件和线程重构一个旧的C项目。目前,全局状态变量在许多地方是在没有同步的情况下写入/读取的,并且通过变量命名约定松散地关联。我想将相关变量分组到全局共享结构中,每个结构都包含一个用于线程安全的互斥锁,如下所示: //将包含跨多个线程写入/读取的数据的结构 类型定义结构{ pthread_mutex_t mutex; int Field1; 浮子场2; }我的结构; 我还想将互斥锁和错误检查放在函数中,如下所示: int SetField1(MyStruct*my_struct,in

我正在用多个文件和线程重构一个旧的C项目。目前,全局状态变量在许多地方是在没有同步的情况下写入/读取的,并且通过变量命名约定松散地关联。我想将相关变量分组到全局共享结构中,每个结构都包含一个用于线程安全的互斥锁,如下所示:

//将包含跨多个线程写入/读取的数据的结构
类型定义结构{
pthread_mutex_t mutex;
int Field1;
浮子场2;
}我的结构;
我还想将互斥锁和错误检查放在函数中,如下所示:

int SetField1(MyStruct*my_struct,int field_1){
int互斥锁错误;
mutex_lock_error=pthread_mutex_lock(&(my_struct->mutex));
如果(!互斥锁错误){
我的结构->字段1=字段1;
pthread_mutex_unlock(&(my_struct->mutex));
}
返回互斥锁错误;
}
int GetField1(MyStruct*my_struct,int*field_1){
int互斥锁错误;
mutex_lock_error=pthread_mutex_lock(&(my_struct->mutex));
如果(!互斥锁错误){
*field_1=我的结构->Field1;
pthread_mutex_unlock(&(my_struct->mutex));
}
返回互斥锁错误;
}
但是,由于并非所有结构成员都是相同的类型,并且具有不同的名称,因此我也需要这样做:

int SetField2(MyStruct*my_struct,float field_2){
int互斥锁错误;
mutex_lock_error=pthread_mutex_lock(&(my_struct->mutex));
如果(!互斥锁错误){
我的结构->字段2=字段2;
pthread_mutex_unlock(&(my_struct->mutex));
}
返回互斥锁错误;
}
int GetField2(MyStruct*my_struct,float*field_2){
int互斥锁错误;
mutex_lock_error=pthread_mutex_lock(&(my_struct->mutex));
如果(!互斥锁错误){
*field_2=我的结构->Field2;
pthread_mutex_unlock(&(my_struct->mutex));
}
返回互斥锁错误;
}
这是很多类似的代码,这个结构只有两个不同的成员。是否有一种标准的方法可以做到这一点,而不需要为每个结构成员使用单独的get/set函数

我想到的可能的解决办法 传入第二个MyStruct/*MyStruct类型的参数(调用者的本地参数)并将值复制到该参数中,因此只需要一个get和一个set函数。这似乎会混淆代码的意图,还有一个巨大的缺点,就是每次写入之前都需要读取状态,这样其他字段就不会受到影响

一些可怕的巫术,使用*void、sizeof、offsetof和传递字节数作为参数。我还没有尝试过实现它,而且可能不会,因为它带来的问题比它解决的问题多得多(甚至更糟)


注意-编译器较旧(gcc 4.1.2),因此我没有访问_Generic的权限。我正在改变这一点,但不能指望它会很快发生。

您可能可以编写一个宏来实现这一点。
带来的问题远比它解决的问题要多得多(甚至更糟)。您将花费数天的时间来优化您只需在几秒钟内使用ctrl+c+v和一些类型更改即可完成的操作。只需编写所有访问器函数。“在每次写入之前都需要读取状态,这样其他字段就不会受到影响,这是一个巨大的缺点。”事实上,这种想法根本行不通,因为只要
get
函数返回,调用方的本地副本就会过期。一种可能的解决方案是编写代码生成器。代码生成器以结构定义作为输入,并创建一个.c文件和一个.h文件,其中包含所有setter和getter。在另一些情况下,它会使您相信线程同步问题已经得到了解决,而事实并非如此。在某些情况下,需要保护的不是简单的单一访问,而是由多个相关访问组成的交互。请务必检查您的用例,以确保在您对特定实现投入过多之前,您的方法将满足您的同步需求。