关于"pure"函数对象的常量和线程安全

About const and thread-safety of "pure" function objects

本文关键字:线程 安全 常量 对象 pure 函数 关于      更新时间:2023-10-16

在我的程序中,有"函数"采用适当的参数,执行一些计算,并返回相应的结果。这些"功能"有一些外部不可见的内部状态;它们主要是临时结果的内存缓冲区。这意味着,这些"函数"没有任何逻辑状态。

这些内存缓冲区和其他内容实际上在每次调用之间都在变化,因为所需的缓冲区大小可能会根据输入数据而变化。

虽然这些缓冲区只是临时缓冲区,但我需要控制它们的生存期、构造/破坏线程等。而且我不希望这些临时人员从呼叫站点提供,因为它们的使用只是"功能"的内部。所以我认为这些"函数"需要根据类来实现(而不是有/没有静态变量的函数)。

由于没有外部可见的状态更改(尽管有些状态在构造后给定并且永远不会更改),我认为最好用const限定函数(我的意思是函数调用运算符或其他什么)。但是我不确定我应该如何处理这些临时资源的线程安全,因为众所周知,在 C++11 中,默认情况下const意味着线程安全。

目前函数的使用主要是单线程的;只有极少数情况下,这些函数的实例由多个线程共享,所以我在真正需要的时候从外部锁定了调用。(更准确地说,有一个锁保护整个计算序列。当另一个线程想要执行计算时,它会获取该锁。当前没有与每个函数关联的锁。

函数的实现与外部分离,因为我计划在其他项目中使用它们。

在函数实现中使用锁保护计算是否更好?或者只是让函数非常量,尽管它们只是(至少在概念上)纯函数?或者只是将它们标记为const尽管它们不是线程安全的(所以不是真正的"const")?还是我应该考虑不同的方法?

最简单的解决方案是使用thread_local缓冲区。

int T::myfunction(int arg) const
{
static thread_local U mybuffer;
// impl...
}

thread_local将为您提供线程安全性,因为每个线程都将使用自己的缓冲区。由于缓冲区static函数内部,因此缓冲区将在每次函数调用后保留。