缓存的getter/calculations模式|具有依赖项跟踪的boost类

cached getter/calculations pattern|boost class with dependency tracking

本文关键字:依赖 跟踪 boost getter calculations 模式 缓存      更新时间:2023-10-16

对于"缓存计算"/"缓存getter",是否有通用模式或准备使用boost类?

我的意思是:

class Test{
public:
     Value getValue() const;
protected:
     Value calculateValue() const;//REALLY expensive operation.
     mutable bool valueIsDirty;
     mutable Value cachedValue;
}
Value Test::getValue() const{
     if (valueIsDirty){
         cachedValue = calculateValue();
         valueIsDirty = false;
     }
     return cachedValue;
}

我可以使用std::pair<Value, bool>并将getValue/calculateValue转换为宏,但如果值依赖于其他值(存储在其他类中),并且这些值也可以缓存,则这并没有真正的帮助。

对于这种"模式",有现成的解决方案吗?目前,我手动处理这样的缓存值,但这并不"好看"。

限制:
c++03标准。允许Boost。

Proxy设计模式可以帮助实现这一点。

一个典型的实现将定义一个类ValuePtr,它的行为与普通的Value*一样,即它有一个过载的operator->operator*。但是,这些运算符并不直接访问底层Value对象,而是包含决定加载或重新计算实际值的逻辑。这种额外的间接级别将封装代理逻辑。

如果您需要计算对其他对象的引用,也许std::shared_ptr<Value>可以用作ValuePtr中的underyling数据类型。

有关代码示例,请参阅此网站。提升。Flyweight也可能有所帮助。

这就是我最终使用的:

template<typename T, typename Owner> class CachedMemberValue{
public:
    typedef T (Owner::*Callback)() const;
    T get(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    const T& getRef(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    void markDirty(){
        dirty = true;
    }
    CachedMemberValue(Owner* owner_, Callback calculateCallback_)
        :owner(owner_), calculateCallback(calculateCallback_), dirty(true){
    }
protected:
    Owner *owner;
    Callback calculateCallback;
    bool dirty;
    T cachedValue;
private:
    CachedMemberValue(const CachedMemberValue<T, Owner>&){
    }
    CachedMemberValue<T, Owner>& operator=(const CachedMemberValue<T, Owner>&){
        return *this;
    }
};

用法:

class MyClass{
    public:
        int getMin() const{
            return cachedMin.get();
                }
            void modifyValue() { /*... calculation/modification*/ cachedMin.markDirty();}
        MyClass(): cachedMin(this, &MyClass::noncachedGetMin){}
    private:
        int noncachedGetMin() const{ /*expensive operation here*/ ... }
        mutable CachedMemberValue<int, MyClass> cachedMin;
};