如何在线程安全的C库中有效地实现句柄

时间:2015-07-09 13:47:39

标签: c multithreading optimization shared-libraries c99

我有一个相当复杂的C99一致的共享库。它包含大量全局变量和许多短函数,但用户只能直接使用少量函数。

我想将它重构为一个线程安全的库。为此,我会让用户传递每个函数的句柄。句柄将是一个指向结构的指针,该结构包含以前的全局变量。

在这种情况下,性能很重要,我不想破坏它。在实现句柄时我需要注意什么?例如,典型的函数看起来像这样

void calculate(){
    for (int i=0; i<N; i++){   
        particle[i].x += G * particle[i].y;
        other_function_that_does_something_to_particle();
    }
}

天真地,我会添加一个这样的句柄

void calculate(struct Handle* h){
    for (int i=0; i<h->N; i++){   
        h->particle[i].x += h->G * h->particle[i].y;
        other_function_that_does_something_to_particle(h);
    }
}

看起来效率很低。还有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

传递指针的成本通常很低。它对体系结构有更大的影响,其中参数通过堆栈,而当参数通过寄存器时,参数更小。

使用const指针(指向const数据的指针)。当数据可以被其他线程修改时,使用volatile字段或指针说明符。并使用restrict

所有类型说明符都有一定的影响。例如,在没有restrict的情况下处理多个引用时,即使已经读取了值,编译器也可能被迫重新读取值。等等。

值得一读:https://en.wikipedia.org/wiki/Restrict

答案 1 :(得分:2)

这不一定慢。在某些体系结构上,它甚至可以更快,因为它们必须将全局变量的地址加载到寄存器中(例如ARM)。只需检查您的平台的PCS和ABI,以确保如何最好地传递参数,以便在寄存器中传递句柄/上下文指针。

我会让h本身保持不变,但是:struct Handle * const h。这样可以防止h被意外修改。

如果您可以转到C11,请查看_Thread_local存储类说明符。这可能就是你想要的。但是,如果手动实现可能更有效,则取决于您的系统。