DataBase 作业2(2) 教师:N Yang

本文仅用于作业提交。

二、LRU REPLACER

lru_replacer.h

/**
 * lru_replacer.h
 *
 * Functionality: The buffer pool manager must maintain a LRU list to collect
 * all the pages that are unpinned and ready to be swapped. The simplest way to
 * implement LRU is a FIFO queue, but remember to dequeue or enqueue pages when
 * a page changes from unpinned to pinned, or vice-versa.
 */

#pragma once


#include <memory>
#include <unordered_map>
#include <mutex>
#include "buffer/replacer.h"

using namespace std;
namespace scudb {

template <typename T> class LRUReplacer : public Replacer<T> {
  struct Node {
    Node() {};
    Node(T val) : val(val) {};
    T val;
    shared_ptr<Node> prev;
    shared_ptr<Node> next;
  };
public:
  // do not change public interface
  LRUReplacer();

  ~LRUReplacer();

  void Remove(shared_ptr<Node>& p);

  void Ins(shared_ptr<Node>& p, const T& v);


  void Insert(const T &value);

  bool Victim(T &value);

  bool Erase(const T &value);

  size_t Size();

private:
  shared_ptr<Node> head;
  shared_ptr<Node> tail;
  unordered_map<T,shared_ptr<Node>> map;
  mutable mutex latch;
  // add your member variables here
};

} // namespace cmudb

其中包含的private参数:

head:头指针

tail:尾指针

head和tail都会在构造时初始化

map:一个由指定类型T对应于指针的映射

其中包含的函数接口:

构造函数和析构函数:

LRUReplacer();

 ~LRUReplacer();

对于节点的删除:

void Remove(shared_ptr<Node>& p);

对于在节点p后插入映射值为v的节点:

void Ins(shared_ptr<Node>& p, const T& v);

以上两个基本函数在以下函数被调用:

插入函数:

void Insert(const T &value);

去除尾节点:

 bool Victim(T &value);

删除函数:

bool Erase(const T &value);

返回全体的数据数量:

size_t Size();

lru_replacer.cpp:

主要的函数如下:

对于节点的删除:

template<typename T> void LRUReplacer<T>::Remove(shared_ptr<Node>& p)//去除p节点,并把原先p之前的节点和原先p之后的节点相连
    {
        shared_ptr<Node> p1 = p->prev;
        shared_ptr<Node> p2 = p->next;
        p->next->prev = p1;
        p->prev->next = p2;
    }

对于在节点p后插入映射值为v的节点:

template<typename T> void LRUReplacer<T>::Ins(shared_ptr<Node>& p,const T &v)//在p节点后增加一个映射值为v的节点
    {
        shared_ptr<Node> p1;
        p->next->prev = p1;
        p1->next = p->next;
        p1->prev = p;
        p->next = p1;
        map[v] = p1;
    }

插入函数:

插入时如果发现原数据存在,那么先覆盖它,之后把需要插入的节点调整到head之后。

template <typename T> void LRUReplacer<T>::Insert(const T& v) {
        lock_guard<mutex> lck(latch);
        shared_ptr<Node> cur;
        if (map.find(v) == map.end())//如果并没有在已有数据中找到
            cur = make_shared<Node>(v);
        else {//如果在已有数据中找到,那么先替代原节点
            cur = map[v];
            shared_ptr<Node> pre = cur->prev;
            pre->next = cur->next;
            shared_ptr<Node> suc = cur->next;
            suc->prev = pre;
        }//之后插入把需要插入的节点安排在head之后
        shared_ptr<Node> fir = head->next;
        cur->prev = head;
        cur->next = head->next;
        fir->prev = cur;
        head->next = cur;
        map[v] = cur;
        return;
    }

去尾函数:

找到最后一个节点(非tail节点),之后把前一个节点和tail拼接,然后删除的节点映射从map删除。

 //去尾函数
    template <typename T> bool LRUReplacer<T>::Victim(T& v) {
        //lock_guard<mutex> lck(latch);
        //如果map非空,说明有节点可以去掉,之后记录倒数第二个节点(不包含尾节点)的信息,然后把该节点和尾结点去掉,需要删除的节点的map映射对应抹去
        if (!(map.empty())) {
            shared_ptr<Node> endone = tail->prev;
            tail->prev = tail->prev->prev;
            endone->prev->next = tail;
            map.erase(endone->val);
            v = endone->val;
            return true;
        }
        return false;
    }

删除函数:

//删除函数
    template <typename T> bool LRUReplacer<T>::Erase(const T& v) {
        //lock_guard<mutex> lck(latch);
        //如果找到对应项,那么就把对应项的前后两个节点拼接,之后删除
        if (map.find(v) != map.end()) {
            shared_ptr<Node> cur = map[v];
            shared_ptr<Node> p = cur->prev;
            shared_ptr<Node> n = cur->next;
            cur->next->prev = p;
            cur->prev->next = n;
        }
        return map.erase(v);
    }

完整代码如下:

/**
 * LRU implementation
 */
#include "buffer/lru_replacer.h"
#include "page/page.h"

namespace scudb {

    template <typename T> LRUReplacer<T>::LRUReplacer() {
        head = make_shared<Node>();
        tail = make_shared<Node>();
        head->next = tail;
        tail->prev = head;
    }

    template <typename T> LRUReplacer<T>::~LRUReplacer() {}


    template<typename T> void LRUReplacer<T>::Remove(shared_ptr<Node>& p)//去除p节点,并把原先p之前的节点和原先p之后的节点相连
    {
        shared_ptr<Node> p1 = p->prev;
        shared_ptr<Node> p2 = p->next;
        p->next->prev = p1;
        p->prev->next = p2;
    }

    template<typename T> void LRUReplacer<T>::Ins(shared_ptr<Node>& p,const T &v)//在p节点后增加一个映射值为v的节点
    {
        shared_ptr<Node> p1;
        p->next->prev = p1;
        p1->next = p->next;
        p1->prev = p;
        p->next = p1;
        map[v] = p1;
    }

    /*
     * Insert value into LRU
     */
     //插入函数
    template <typename T> void LRUReplacer<T>::Insert(const T& v) {
        lock_guard<mutex> lck(latch);
        shared_ptr<Node> cur;
        if (map.find(v) == map.end())//如果并没有在已有数据中找到
            cur = make_shared<Node>(v);
        else {//如果在已有数据中找到,那么先删除原节点
            cur = map[v];
            Remove(cur);
            map.erase(v);
        }//之后插入把需要插入的节点安排在head之后
        Ins(head, v);
        return;
    }

    /* If LRU is non-empty, pop the head member from LRU to argument "value", and
     * return true. If LRU is empty, return false
     */
     //去尾函数
    template <typename T> bool LRUReplacer<T>::Victim(T& v) {
        //lock_guard<mutex> lck(latch);
        //如果map非空,说明有节点可以去掉,之后记录倒数第二个节点(不包含尾节点)的信息,然后把该节点和尾结点去掉,需要删除的节点的map映射对应抹去
        if (!(map.empty())) {
            shared_ptr<Node> endone = tail->prev;
            Remove(endone);
            return true;
        }
        return false;
    }

    /*
     * Remove value from LRU. If removal is successful, return true, otherwise
     * return false
     */
     //删除函数
    template <typename T> bool LRUReplacer<T>::Erase(const T& v) {
        //lock_guard<mutex> lck(latch);
        //如果找到对应项,那么就把对应项的前后两个节点拼接,之后删除
        if (map.find(v) != map.end()) {
            shared_ptr<Node> cur = map[v];
            Remove(cur);
        }
        return map.erase(v);
    }

    template <typename T> size_t LRUReplacer<T>::Size() {
        //lock_guard<mutex> lck(latch);
        return map.size();
    }

    template class LRUReplacer<Page*>;
    // test only
    template class LRUReplacer<int>;

} // namespace cmudb

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值