#pragma once #include "KArcCacheNode.h" #include #include #include namespace KamaCache { template class ArcLfuPart { public: using NodeType = ArcNode; using NodePtr = std::shared_ptr; using NodeMap = std::unordered_map; using FreqMap = std::map>; explicit ArcLfuPart(size_t capacity, size_t transformThreshold) : capacity_(capacity) , ghostCapacity_(capacity) , transformThreshold_(transformThreshold) , minFreq_(0) { initializeLists(); } bool put(Key key, Value value) { if (capacity_ == 0) return false; std::lock_guard lock(mutex_); auto it = mainCache_.find(key); if (it != mainCache_.end()) { return updateExistingNode(it->second, value); } return addNewNode(key, value); } bool get(Key key, Value& value) { std::lock_guard lock(mutex_); auto it = mainCache_.find(key); if (it != mainCache_.end()) { updateNodeFrequency(it->second); value = it->second->getValue(); return true; } return false; } bool contain(Key key) { return mainCache_.find(key) != mainCache_.end(); } bool checkGhost(Key key) { auto it = ghostCache_.find(key); if (it != ghostCache_.end()) { removeFromGhost(it->second); ghostCache_.erase(it); return true; } return false; } void increaseCapacity() { ++capacity_; } bool decreaseCapacity() { if (capacity_ <= 0) return false; if (mainCache_.size() == capacity_) { evictLeastFrequent(); } --capacity_; return true; } private: void initializeLists() { ghostHead_ = std::make_shared(); ghostTail_ = std::make_shared(); ghostHead_->next_ = ghostTail_; ghostTail_->prev_ = ghostHead_; } bool updateExistingNode(NodePtr node, const Value& value) { node->setValue(value); updateNodeFrequency(node); return true; } bool addNewNode(const Key& key, const Value& value) { if (mainCache_.size() >= capacity_) { evictLeastFrequent(); } NodePtr newNode = std::make_shared(key, value); mainCache_[key] = newNode; // 将新节点添加到频率为1的列表中 if (freqMap_.find(1) == freqMap_.end()) { freqMap_[1] = std::list(); } freqMap_[1].push_back(newNode); minFreq_ = 1; return true; } void updateNodeFrequency(NodePtr node) { size_t oldFreq = node->getAccessCount(); node->incrementAccessCount(); size_t newFreq = node->getAccessCount(); // 从旧频率列表中移除 auto& oldList = freqMap_[oldFreq]; oldList.remove(node); if (oldList.empty()) { freqMap_.erase(oldFreq); if (oldFreq == minFreq_) { minFreq_ = newFreq; } } // 添加到新频率列表 if (freqMap_.find(newFreq) == freqMap_.end()) { freqMap_[newFreq] = std::list(); } freqMap_[newFreq].push_back(node); } void evictLeastFrequent() { if (freqMap_.empty()) return; // 获取最小频率的列表 auto& minFreqList = freqMap_[minFreq_]; if (minFreqList.empty()) return; // 移除最少使用的节点 NodePtr leastNode = minFreqList.front(); minFreqList.pop_front(); // 如果该频率的列表为空,则删除该频率项 if (minFreqList.empty()) { freqMap_.erase(minFreq_); // 更新最小频率 if (!freqMap_.empty()) { minFreq_ = freqMap_.begin()->first; } } // 将节点移到幽灵缓存 if (ghostCache_.size() >= ghostCapacity_) { removeOldestGhost(); } addToGhost(leastNode); // 从主缓存中移除 mainCache_.erase(leastNode->getKey()); } void removeFromGhost(NodePtr node) { if (!node->prev_.expired() && node->next_) { auto prev = node->prev_.lock(); prev->next_ = node->next_; node->next_->prev_ = node->prev_; node->next_ = nullptr; // 清空指针,防止悬垂引用 } } void addToGhost(NodePtr node) { node->next_ = ghostTail_; node->prev_ = ghostTail_->prev_; if (!ghostTail_->prev_.expired()) { ghostTail_->prev_.lock()->next_ = node; } ghostTail_->prev_ = node; ghostCache_[node->getKey()] = node; } void removeOldestGhost() { NodePtr oldestGhost = ghostHead_->next_; if (oldestGhost != ghostTail_) { removeFromGhost(oldestGhost); ghostCache_.erase(oldestGhost->getKey()); } } private: size_t capacity_; size_t ghostCapacity_; size_t transformThreshold_; size_t minFreq_; std::mutex mutex_; NodeMap mainCache_; NodeMap ghostCache_; FreqMap freqMap_; NodePtr ghostHead_; NodePtr ghostTail_; }; } // namespace KamaCache