我正在尝试实现一个缓存,该缓存必须(显然)针对获取和回收项目进行优化。
但存在一个挑战:缓存可能会不时失效。
从架构的角度来看,到目前为止我所做的是实现包含池的缓存。该池本身实际上是一个无锁对象池,经过充分测试并且可以正常工作。
一个问题是允许池本身与更新版本进行交换。我认为我已经进行了交换(参考:两个 unique_ptr<T> 的无锁交换)。
但是如何使用可以在操作期间交换的池(分别是下面的 getPreparedDefaultRule() 和 recyclePreparedDefaultRule())来处理无锁 get 和 set 呢?
我几乎认为这是不可能的。尽管我很高兴被证明是错误的。
template <typename Data, typename Delegate>
class DefaultRulePoolCache {
public:
    DefaultRulePoolCache() : _atomicDefaultRulePool(nullptr), _defaultRulePool(nullptr) {
        
    }
    
    std::unique_ptr<detail::PreparedRule<Data, Delegate>> getPreparedDefaultRule() {
        auto atomicPool = _atomicDefaultRulePool.load();
        if (!atomicPool) {
            return nullptr;
        }
        return atomicPool->getPreparedRule();
    }
    
    void recyclePreparedDefaultRule(std::unique_ptr<detail::PreparedRulePool<Data, Delegate>> preparedRule) {
        auto atomicPool = _atomicDefaultRulePool.load();
        if (!atomicPool) {
            return;
        }
        hdmCheck(preparedRule) << "Cannot recycle null rule.";
        // we return the prepared rule only to the pool in case it's the current version of the default rul
        if (atomicPool->getTag() == preparedRule->getTag()) {
            atomicPool->recyclePreparedRule(std::move(preparedRule));
        }
    }
    
    void setDefaultRulePool(std::shared_ptr<detail::PreparedRulePool<Data, Delegate>> defaultRulePool) {
        std::lock_guard<std::mutex> lock(_defaultRulePoolMutex);
        atomicSwapPool(defaultRulePool);
    }
    
    void removeDefaultRulePool() {
        std::lock_guard<std::mutex> lock(_defaultRulePoolMutex);
        atomicSwapPool(nullptr);
    }
private:
    std::atomic<detail::PreparedRulePool<Data, Delegate>*> _atomicDefaultRulePool;
    std::shared_ptr<detail::PreparedRulePool<data::Location, KVOLocationValuesDelegate>> _defaultRulePool;    
    std::mutex _defaultRulePoolMutex;
    
    void atomicSwapPool(std::shared_ptr<detail::PreparedRulePool<Data, Delegate>> defaultRulePool) {
       std::atomic_exchange(&_atomicDefaultRulePool, defaultRulePool.get());
        // destroy the old pool
        _defaultRulePool = nullptr;
        // asign the new pool
        _defaultRulePool = defaultRulePool;
    }
};
| 归档时间: | 
 | 
| 查看次数: | 207 次 | 
| 最近记录: |