Untitled
unknown
c_cpp
a year ago
3.5 kB
10
Indexable
//===----------------------------------------------------------------------===// // // BusTub // // lru_k_replacer.cpp // // Identification: src/buffer/lru_k_replacer.cpp // // Copyright (c) 2015-2022, Carnegie Mellon University Database Group // //===----------------------------------------------------------------------===// #include "buffer/lru_k_replacer.h" #include "common/exception.h" namespace bustub { LRUKReplacer::LRUKReplacer(size_t num_frames, size_t k) : replacer_size_(num_frames), k_(k) {} auto LRUKReplacer::Evict(frame_id_t *frame_id) -> bool { std::lock_guard<std::mutex> lock(latch_); if (curr_size_ == 0) { return false; } // assume the list is sorted if (!smaller_than_k_.empty()) { for (auto n : smaller_than_k_) { if (n->is_evictable_) { *frame_id = n->fid_; this->MyRemove(n->fid_); return true; } } } if (!larger_than_k_.empty()) { for (auto n : larger_than_k_) { if (n->is_evictable_) { *frame_id = n->fid_; this->MyRemove(n->fid_); return true; } } } return false; } void LRUKReplacer::RecordAccess(frame_id_t frame_id, [[maybe_unused]] AccessType access_type) { std::lock_guard<std::mutex> lock(latch_); if (frame_id > static_cast<int>(replacer_size_)) { throw Exception("frame id is invalid"); } current_timestamp_++; if (node_store_.find(frame_id) == node_store_.end()) { // new frame node_store_[frame_id] = LRUKNode(); node_store_[frame_id].fid_ = frame_id; } auto &temp = node_store_[frame_id]; auto original_size = (temp.history_).size(); if (original_size >= k_) { // current in larger_than_k, so need to remove larger_than_k_.erase(&temp); temp.history_.pop_front(); } temp.history_.emplace_back(current_timestamp_); if (original_size == k_) { larger_than_k_.insert(&temp); } else if (original_size == k_ - 1) { smaller_than_k_.erase(smaller_iterators_[frame_id]); smaller_iterators_.erase(frame_id); larger_than_k_.insert(&temp); } else if (original_size == 0) { smaller_than_k_.push_back(&temp); auto it = smaller_than_k_.end(); --it; smaller_iterators_[frame_id] = it; } } void LRUKReplacer::SetEvictable(frame_id_t frame_id, bool set_evictable) { std::lock_guard<std::mutex> lock(latch_); if (frame_id > static_cast<int>(replacer_size_)) { throw Exception("frame id is invalid"); } if (node_store_.find(frame_id) == node_store_.end()) { return; } if (set_evictable && !node_store_[frame_id].is_evictable_) { curr_size_++; } else if (!set_evictable && node_store_[frame_id].is_evictable_) { curr_size_--; } node_store_[frame_id].is_evictable_ = set_evictable; } void LRUKReplacer::MyRemove(frame_id_t frame_id) { auto &temp = node_store_[frame_id]; if (temp.history_.size() < k_) { smaller_than_k_.erase(smaller_iterators_[frame_id]); smaller_iterators_.erase(frame_id); } else { larger_than_k_.erase(&temp); } node_store_.erase(frame_id); curr_size_--; } void LRUKReplacer::Remove(frame_id_t frame_id) { std::lock_guard<std::mutex> lock(latch_); if (node_store_.find(frame_id) == node_store_.end()) { return; } auto &temp = node_store_[frame_id]; if (!temp.is_evictable_) { throw Exception("This frame is not evictable"); } this->MyRemove(frame_id); } auto LRUKReplacer::Size() -> size_t { std::lock_guard<std::mutex> lock(latch_); return curr_size_; } } // namespace bustub
Editor is loading...