在C++中缓存昂贵的数据 - 函数范围的静态与可变成员变量

Dom*_*ger 9 c++ static mutable thread-safety

我有一个相对昂贵的数据获取操作,我想缓存结果.从const方法调用此操作,大致如下:

double AdjustData(double d, int key) const {
  double factor = LongRunningOperationToFetchFactor(key);
  return factor * d;
}
Run Code Online (Sandbox Code Playgroud)

我想AdjustData保留const,但我想缓存因素,所以我只是第一次获取它.目前我使用的是mutable map<int, double>存储的结果(图被keyfactor),但我使用的功能范围的静态可能是一个更好的解决办法思考-这个因素只能通过此功能需要,而且是无关的其他同学.

这似乎是一个好方法吗?还有更好的选择吗?我可以考虑哪些事情,特别是在线程安全方面.

谢谢,

大教堂

Jer*_*rks 5

我会用这样的东西包装LongRunningOperationToFetchFactor的实现.我正在使用Boost范围的锁,但你可以使用与其他锁定框架类似的东西.

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <map>

using namespace std;

static boost::mutex myMutex;
static map<int,double> results;

double CachedLongRunningOperationToFetchFactor( int key )
{

   {
       boost::mutex::scoped_lock lock(myMutex);

       map<int,double>::iterator iter = results.find(key);
       if ( iter != results.end() )
       {
          return (*iter).second;
       }
   }
   // not in the Cache calculate it
   result = LongRunningOperationToFetchFactor( key );
   {
       // we need to lock the map again
       boost::mutex::scoped_lock lock(myMutex);
       // it could be that another thread already calculated the result but
       // map assignment does not care.
       results[key] = result;
   }
   return result;
}
Run Code Online (Sandbox Code Playgroud)

如果这确实是一个长期运行的操作,那么锁定互斥锁的成本应该是最小的.

你的问题不是很清楚,但如果函数LongRunningOperationToFetchFactor是你的类的成员函数,那么你希望map在同一个类中是可变映射.我单个静态互斥锁用于访问仍然足够快.


Joh*_*itb 5

不会将此缓存设为本地静态缓存。可变映射是缓存结果解决方案。否则它会使您的函数无用,因为您的类的不同对象将共享相同的缓存,因为所有对象的本地静态缓存都是相同的。如果结果不依赖于对象,您可以使用本地静态。但是我会问自己为什么该函数是对象的非静态成员,如果它不需要访问它的任何状态。

正如您所说,它应该是线程安全的——如果不同的线程可以调用同一个对象上的成员函数,您可能想要使用互斥锁。boost::thread是一个很好用的库。